SQL性能優化

SQL性能優化

SQL性能優化

一、SQL的執行順序

順序:FROM——ON——JOIN——WHERE——GROUP BY——SUM、COUNT——HAVING——SELECT——DISTINCT——ORDER BY——LIMIT

與寫SQL的順序不同,SQL的執行順序并不是從select開始,而是從from開始

1、FROM:先去獲取from里面的表,拿到對應的數據,生成虛擬表1。

2、ON:對虛擬表1應用ON篩選,符合條件的數據生成虛擬表2。

3、JOIN:根據JOIN的類型去執行相對應的操作,獲取對應的數據,生成虛擬表3。

4、WHERE:對虛擬表3的數據進行條件過濾,符合記錄的數據生成虛擬表4。

5、GROUP BY:根據group by中的列,對虛擬表4進行數據分組操作,生成虛擬表5。

6、CUBE|ROLLUP(聚合函數使用):主要是使用相關的聚合函數,生成虛擬表6。

7、HAVING:對虛擬表6的數據過濾,生成虛擬表7,這個過濾是在where中無法完成的,同時count(expr)返回不為NULL的行數,而count(1)和count(*)是會返回包括NULL在內的行數。

8、SELECT:選擇指定的列,生成虛擬表8。

9、DISTINCT:數據去重,生成虛擬表9。

10、ORDER BY:對虛擬表9中的數據進行指定列的排序,生成虛擬表10。

11、LIMIT:取出指定行的記錄,生成虛擬表11,返回給查詢用戶。

以上是SQL各關鍵詞的執行順序,如果在一條SQL語句里面你沒有用到某個關鍵詞那就不會被執行了。理解SQL的邏輯執行順序對我們在實際寫SQL的過程中也會有幫助的。

二、執行計劃——EXPLAIN

執行計劃,是SQL在數據庫中執行時的表現情況,通常用于SQL性能分析,優化等場景。在MySQL使用 explain 關鍵字來查看SQL的執行計劃。

基本的語法:EXPLAIN(select * from table)

在常規SQL語句前面加上EXPLAIN即可

運行結果:

image

參數解釋:

1、id:數字越大越先執行,一樣大則從上往下執行,如果為NULL則表示是結果集,不需要用來查詢。

2、select_type:

simple:不需要union的操作或者是不包含子查詢的簡單select語句。

primary:需要union操作或者含有子查詢的select語句。

union:連接兩個select查詢,第一個查詢是dervied派生表,第二個及后面的表select_type都是union。

dependent union:與union一樣,出現在union 或union all語句中,但是這個查詢要受到外部查詢的影響。

union result:包含union的結果集。

subquery:除了from字句中包含的子查詢外,其他地方出現的子查詢都可能是subquery。

dependent subquery:與dependent union類似,表示這個subquery的查詢要受到外部表查詢的影響。

derived:from字句中出現的子查詢,也叫做派生表,其他數據庫中可能叫做內聯視圖或嵌套select。

3、table

表名,如果是用了別名,則顯示別名

4、type

依次從好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一個索引。

system:表中只有一行數據或者是空表。

const:使用唯一索引或者主鍵,返回記錄一定是1行記錄的等值where條件時,通常type是const。

eq_ref:出現在要連接過個表的查詢計劃中,驅動表只返回一行數據,且這行數據是第二個表的主鍵或者唯一索引,且必須為not null,唯一索引和主鍵是多列時,只有所有的列都用作比較時才會出現eq_ref。

ref:不像eq_ref那樣要求連接順序,也沒有主鍵和唯一索引的要求,只要使用相等條件檢索時就可能出現,常見與輔助索引的等值查找。

fulltext:全文索引檢索,要注意,全文索引的優先級很高,若全文索引和普通索引同時存在時,mysql不管代價,優先選擇使用全文索引。

ref_or_null:與ref方法類似,只是增加了null值的比較。實際用的不多。

unique_subquery:用于where中的in形式子查詢,子查詢返回不重復值唯一值。

index_subquery:用于in形式子查詢使用到了輔助索引或者in常數列表,子查詢可能返回重復值,可以使用索引將子查詢去重。

range:索引范圍掃描,常見于使用>,<,is null,between ,in ,like等運算符的查詢中。

index_merge:表示查詢使用了兩個以上的索引,最后取交集或者并集,常見and ,or的條件使用了不同的索引。

index:索引全表掃描,把索引從頭到尾掃一遍,常見于使用索引列就可以處理不需要讀取數據文件的查詢、可以使用索引排序或者分組的查詢。

all:這個就是全表掃描數據文件,然后再在server層進行過濾返回符合要求的記錄。

5、possible_keys:查詢可能使用到的索引。

6、key:查詢真正使用到的索引。

7、key_len:用于處理查詢的索引長度。

8、ref:常數等值查詢顯示const,連接查詢則顯示表的關聯字段。

9、rows:執行計劃中估算的掃描行數,不是精確值。

10、filtered:表示存儲引擎返回的數據在server層過濾后,剩下多少滿足查詢的記錄數量的比例。

11、extra:該字段信息較多,這里就不一一敘述了。

在實際的使用過程中我們需要重點去關注type、key、key_len、rows、extra這幾個參數,type要努力優化到range級別,all要盡量少的出現,在查詢的過程中要盡量使用索引,提高效率,在extra里面出現Using filesort, Using temporary是不太好的,要去優化提高性能。

三、優化TIPS

1、盡量少用select *

因為會增加不必要的消耗,select 后面直接加上需要的字段名。

2、IN 包含的值不應過多

IN本身這個操作消耗就比較高,如果IN里面是連續的數值,則可以用between代替,IN里面的字段如果是添加了索引,效率還是可以的,目前測試一萬以內還是可以,但是超過了結果可能會有點爆炸,不要問我為什么

3、in和exists、not in 和 not exists

exists以外層表為驅動表,先被訪問,適合于外表小而內表大的情況。

in則是先執行子查詢,適合外表大而內表小的情況,

一般情況是不推薦使用not in,因為效率非常低,

eg:

1)select * from table_a where table_a.id not in (select table_b.id from table_b)

2)select * from table_a left join table_b on table_a.id = table_b.id where table_b.id is null

語句2的效率是要高于語句1的,SQL的結果是獲取到在table_a中存在但是table_b中不存在的數據,如果直接用not in是不走索引的,而且在table_b比較大的時候效率會非常低,實際工作中我試了一下直接not in,然后數據達到一萬條的時候大概需要150S左右才能查出數據(感謝DBA和運維不殺之恩),我采取的方法是,先查出兩個表的交集,這樣得到的表會小很多,而且是用的in,效率會高很多,然后再用not in,最終的效果也是一樣,但是時間只要2.56S,然后采取語句2的關聯表來處理,時間縮短到了1.42S,基本上效率是比較高的,當然理想的是在1S內。

4、盡量少用or,同時盡量用union all 代替union

or兩邊的字段如果有不走索引的會導致整個的查詢不走索引,從而導致效率低下,這時可以使用union all或者union,而兩者的區別是union是將兩個結果合并之后再進行唯一性的過濾操作,效率會比union all低很多,但是union all需要兩個數據集沒有重復的數據。

5、分段和分頁查詢

在掃描行數較多的情況下可以采取分段查詢,循環遍歷,結果合并處理,

使用合理的分頁方式,在數據表量級逐漸增加的時候,limit分頁查詢的效率會降低。

1)select id,col from table limit 888888,1000

2)select id,col from table where id > 888887 limit 1000

取前一頁的最大行數的id,然后根據這個id來限制下一頁的起點。

6、不建議使用%前綴模糊查詢

like "%abc"和like "%abc%"會導致索引失效而進行全文搜索。

如果你還有什么比較好的優化tips歡迎分享!

</article>

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容