mysql 索引,以及sql優化總結

sql問題

where執行順序

如果查詢的所有條件都沒有索引,則不分先後順序(在500W數據下試過,沒有太大差別),如果有索引,mysql會根據sql條件進行優化,比如先執行查詢符合索引的條件。

下面這個因爲test2表的a字段是索引,所以會先執行a的條件

在where都有索引的情況下 按照from的順序

在where都無索引的情況下

 

join的問題

小表驅動大表,減少遍歷次數

小表(篩選條件後) left join 大表(篩選條件後)。

 

count的問題

count(1),count(*) 統計所有行,包含值爲null的

count(字段) 值統計不爲null的。

具體來說 count(1)和count(*) 沒有太大區別。

如果表沒有主鍵,那麼count(1)比count(*)快。

如果有主鍵,那麼count(主鍵,聯合主鍵)比count(*)快。

如果表只有一個字段,count(*)最快。

 

聯合索引

基礎

講聯合索引,一定要扯最左匹配!放心,我不扯有的沒的,幾句話懂個大概就行!

最左匹配

所謂最左原則指的就是如果你的 SQL 語句中用到了聯合索引中的最左邊的索引,那麼這條 SQL 語句就可以利用這個聯合索引去進行匹配,值得注意的是,當遇到範圍查詢(>、<、between、like)就會停止匹配。

假設,我們對(a,b)字段建立一個索引,也就是說,你where後條件爲

a = 1
a = 1 and b = 2

是可以匹配索引的。但是要注意的是~你執行

b= 2 and a =1

也是能匹配到索引的,因爲Mysql有優化器會自動調整a,b的順序與索引順序一致。 相反的,你執行

b = 2

就匹配不到索引了。 而你對(a,b,c,d)建立索引,where後條件爲

a = 1 and b = 2 and c > 3 and d = 4

那麼,a,b,c三個字段能用到索引,而d就匹配不到。因爲遇到了範圍查詢!

最左匹配的原理?

假設,我們對(a,b)字段建立索引,那麼入下圖所示

 

如圖所示他們是按照a來進行排序,在a相等的情況下,才按b來排序。

因此,我們可以看到a是有序的1,1,2,2,3,3。而b是一種全局無序,局部相對有序狀態! 什麼意思呢?

從全局來看,b的值爲1,2,1,4,1,2,是無序的,因此直接執行b = 2這種查詢條件沒有辦法利用索引。

從局部來看,當a的值確定的時候,b是有序的。例如a = 1時,b值爲1,2是有序的狀態。當a=2時候,b的值爲1,4也是有序狀態。 因此,你執行a = 1 and b = 2是a,b字段能用到索引的。而你執行a > 1 and b = 2時,a字段能用到索引,b字段用不到索引。因爲a的值此時是一個範圍,不是固定的,在這個範圍內b值不是有序的,因此b字段用不上索引。

綜上所示,最左匹配原則,在遇到範圍查詢的時候,就會停止匹配。

實戰

OK,懂上面的基礎,我們就可以開始扯了~我舉了經典的五大題型,看完基本就懂!

注意如果 建立了(a,b,c)的聯合索引,where a,b,c 和 where a,c,b 的條件順序沒有區別,musql會自動優化。

題型一

如果sql爲

SELECT * FROM table WHERE a = 1 and b = 2 and c = 3;

如何建立索引?

如果此題回答爲對(a,b,c)建立索引,那都可以回去等通知了。 此題正確答法是,(a,b,c)或者(c,b,a)或者(b,a,c)都可以,重點要的是將區分度高的字段放在前面,區分度低的字段放後面。像性別、狀態這種字段區分度就很低,我們一般放後面。

例如假設區分度由大到小爲b,a,c。那麼我們就對(b,a,c)建立索引。在執行sql的時候,優化器會 幫我們調整where後a,b,c的順序,讓我們用上索引。

題型二

如果sql爲

SELECT * FROM table WHERE a > 1 and b = 2;

如何建立索引?

如果此題回答爲對(a,b)建立索引,那都可以回去等通知了。 此題正確答法是,對(b,a)建立索引。如果你建立的是(a,b)索引,那麼只有a字段能用得上索引,畢竟最左匹配原則遇到範圍查詢就停止匹配。 如果對(b,a)建立索引那麼兩個字段都能用上,優化器會幫我們調整where後a,b的順序,讓我們用上索引。

題型三

如果sql爲

SELECT * FROM `table` WHERE a > 1 and b = 2 and c > 3;

如何建立索引? 此題回答也是不一定,(b,a)或者(b,c)都可以,要結合具體情況具體分析。

拓展一下

SELECT * FROM `table` WHERE a = 1 and b = 2 and c > 3;

怎麼建索引?嗯,大家一定都懂了!

題型四

SELECT * FROM `table` WHERE a = 1 ORDER BY b;

如何建立索引? 這還需要想?一看就是對(a,b)建索引,當a = 1的時候,b相對有序,可以避免再次排序! 那麼

SELECT * FROM `table` WHERE a > 1 ORDER BY b;

如何建立索引? 對(a)建立索引,因爲a的值是一個範圍,這個範圍內b值是無序的,沒有必要對(a,b)建立索引。

拓展一下

SELECT * FROM `table` WHERE a = 1 AND b = 2 AND c > 3 ORDER BY c;

怎麼建索引?

題型五

SELECT * FROM `table` WHERE a IN (1,2,3) and b > 1;

如何建立索引?

還是對(a,b)建立索引,因爲IN在這裏可以視爲等值引用,不會中止索引匹配,所以還是(a,b)!

拓展一下

SELECT * FROM `table` WHERE a = 1 AND b IN (1,2,3) AND c > 3 ORDER BY c;

如何建立索引?此時c排序是用不到索引的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章