引言
本文主要介紹MySQL中,有關慢查詢的優化方案。
慢查詢日志是mysql的一個日志記錄,可以用來記錄mysql語句執行時間超過指定的long_query_time的SQL語句,long_query_time的默認值是10s
慢查詢日志默認情況下是不開啟的,因為將數據保存到日志會對性能有一定影響,測試環境下可手動打開,但注意手動開啟之后只對本次啟動生效,mysql關閉之后重啟恢復默認狀態,要想持久生效要改變my.ini配置文件(Window系統下),其他系統變量也如此。可通過show varaibles like '%slow_query_log%'來查看日志開啟情況
查詢優化
explain+SQL語句
執行這個語句可以讓開發人員看到select語句執行的詳細信息,開發人員可以將上一步慢查詢中捕獲的慢查詢SQL語句進行分析,判斷查詢效率低的可能原因
id:select查詢的序號
id相同時,則按照從上到下依次執行 id不同時,id值越大優先級越高,越先被執行 id有相同有不同,則相同的id為一個組,不同組的id值按照規則二的優先級執行,同組id則按照規則一依次執行
select_type:select查詢的類型
simple:表示該查詢沒有子查詢和UNION連接查詢 primary:有子查詢時的最外層查詢 subquery:有子查詢時的內層嵌套查詢 derived:在from中包含的select就稱為derived(衍生) ,mysql會遞歸這些子查詢,把結果放在臨時表中 union:union的第二個或者最后一個 union result:union的結果
table:執行當前SQL語句中用的表
partitions:代表當前表所使用的分區
type:顯示使用了何種查詢,按照常見的幾種查詢最好到最壞排序為system>const>eq_ref>ref>range>index>all
system,const:mysql能夠對這部分進行查詢優化使能夠將其轉換成一個常量(system只返回一行,const有多行),如某一行的主鍵放入WHERE子句里的方式來選取此行的主鍵,MySQL就能將這個查詢轉換成一個常量。然后就可以高效的將表從聯接執行中移除 eq_ref:使用該索引查找,mysql知道最多返回一條數據,可以在使用主鍵或者唯一性索引查找時用到 ref:非唯一性索引的索引查找 range:范圍掃描,例如帶有between或者>,<,in等 index:掃描所有索引行 all:掃描所有數據行
possible_keys/kesy:代表可能用到的索引和實際用到的索引
key_len:在索引中使用的字節數
ref:顯示了之前的表在key列記錄的索引中查找值所用的列或常量
rows:mysq估計的要找到滿足條件的行所需要掃描的行數
show profile
show profile是mysql用來分析SQL查詢語句的資源使用情況的工具
我們執行一些測試的SQL語句之后運行show profiles語句
我們可以選擇指定項指定SQL語句來分析
一般我們查看的屬性就是cpu和block io兩個模塊
注意:
若出現以下任意一個情況,都表示這是一個糟糕的SQL語句,需要優化
- convering heap to MyIsam查詢結果過大,內存不夠,需要記錄到磁盤上
- creating tmp table創建臨時表儲存數據,用完之后刪除
- copying to tmp table on disk將臨時表中的數據儲存到磁盤上
- locked
索引優化
哪些情況需要建索引?
- 主鍵,唯一索引
- 經常用做查詢條件的建立索引
- 經常需要排序、分組、統計的建立索引
- 查詢中與其他表關聯,外鍵關系建立索引
哪些情況不要建索引?
- 表記錄太少,百萬級一下不需要建索引
- 經常增刪改的表
- 數據重復且分布均勻的數據:如true、false
- 頻發更新字段
- where條件里用不到的字段
緩存優化
一般Java提供的ORM中都帶有相關查詢的一二級緩存。