關於數據量過大如何優化查詢
對於互聯網公司來說,一周的數據量超過數十萬甚至幾百萬已經是家常便飯,在這樣一個數據爆炸的時代,找到一個好的數據庫存儲是非常重要的,mysql就是其中之一,但是,對於mysql來說,如果數據量超過100W,則查詢的性能會下降得非常厲害。
對於單表的查詢優化
在我看來,如果每個表的數據量最好在100W左右(特別是對於一些表的字段特別多的時候),如果字段比較少的話,可以達到500W,因為對於mysql來說,單表的性能仍是比較可觀的。
對於字段而言:
- 盡量使用TINYINT、SMALLINT、MEDIUM_INT作為整數類型而非INT,如果非負則加上UNSIGNED
- VARCHAR的長度只分配真正需要的空間
- 使用枚舉或整數代替字符串類型
- 盡量使用TIMESTAMP而非DATETIME,
- 單表不要有太多字段,建議在20以內
- 避免使用NULL字段,很難查詢優化且占用額外索引空間
- 用整型來存IP
索引:
- 索引並不是越多越好,要根據查詢有針對性的創建,考慮在WHERE和ORDER BY命令上涉及的列建立索引,可根據EXPLAIN來查看是否用了索引還是全表掃描
- 應盡量避免在WHERE子句中對字段進行NULL值判斷,否則將導致引擎放棄使用索引而進行全表掃描
- 值分布很稀少的字段不適合建索引,例如"性別"這種只有兩三個值的字段
- 字符字段最好不要做主鍵
- 不用外鍵,由程序保證約束
- 盡量不用UNIQUE,由程序保證約束
- 使用多列索引時主意順序和查詢條件保持一致,同時刪除不必要的單列索引
查詢SQL:
- 可通過開啟慢查詢日志來找出較慢的SQL
- 不做列運算:SELECT id WHERE age + 1 = 10,任何對列的操作都將導致表掃描,它包括數據庫教程函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊
- sql語句盡可能簡單:一條sql只能在一個cpu運算;大語句拆小語句,減少鎖時間;一條大sql可以堵死整個庫
- 不用SELECT *
- OR改寫成IN:OR的效率是n級別,IN的效率是log(n)級別,in的個數建議控制在200以內
- 不用函數和觸發器,在應用程序實現
- 避免%xxx式查詢
- 少用JOIN
- 使用同類型進行比較,比如用'123'和'123'比,123和123比
- 盡量避免在WHERE子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描
- 對於連續數值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
- 列表數據不要拿全表,要使用LIMIT來分頁,每頁數量也不要太大
升級硬件
Scale up,這個不多說了,根據MySQL是CPU密集型還是I/O密集型,通過提升CPU和內存、使用SSD,都能顯著提升MySQL性能
參照:http://database.51cto.com/art/201608/515550.htm