MySql最左字首原則
B-Tree 索引和 Hash 索引的對比 對於 B-tree 和 hash 資料結構的理解能夠有助於預測不同儲存引擎下使用不同索引的查詢效能的差異,尤其是那些允許你選擇 B-tree 或者 hash 索引的記憶體儲存引擎。
B-Tree 索引的特點
B-tree 索引可以用於使用 =, >, >=, <, <= 或者 BETWEEN 運算子的列比較。如果 LIKE 的引數是一個沒有以萬用字元起始的常量字串的話也可以使用這種索引。
有時,即使有索引可以使用,MySQL 也不使用任何索引。發生這種情況的場景之一就是優化器估算出使用該索引將要求 MySql 去訪問這張表的絕大部分記錄。這種情況下,一個表掃描可能更快,因為它要求更少量的查詢。但是,如果這樣的一個查詢使用了 LIMIT 來檢索只是少量的記錄時,MySql 還是會使用索引,因為它能夠更快地找到這點記錄並將其返回。
Hash 索引的特點
Hash 索引有著與剛才所討論特點的相比截然不同的特點: Hash 索引只能夠用於使用 = 或者 <=> 運算子的相等比較(但是速度更快)。Hash 索引不能夠用於諸如 < 等用於查詢一個範圍值的比較運算子。依賴於這種單值查詢的系統被稱為 “鍵-值儲存”;對於這種系統,儘可能地使用 hash 索引。 優化器不能夠使用 hash 索引來加速 ORDER BY 操作。這種型別的索引不能夠用於按照順序查詢下一個條目。 MySql 無法使用 hash 索引估計兩個值之間有多少行(這種情況由範圍優化器來決定使用哪個索引)。如果你將一張 MyISAM 或 InnoDB 錶轉換成一個 hash 索引的記憶體表時,一些查詢可能會受此影響。 查詢某行記錄必須進行全鍵匹配。而 B-tree 索引,任何該鍵的左字首都可用以查詢記錄。
最左字首原則
通過例項理解單列索引、多列索引以及最左字首原則
例項:現在我們想查出滿足以下條件的使用者id: mysql>SELECT `uid` FROM people WHERE lname`=’Liu’ AND `fname`=’Zhiqun’ AND `age`=26 因為我們不想掃描整表,故考慮用索引。
單列索引: ALTER TABLE people ADD INDEX lname (lname); 將lname列建索引,這樣就把範圍限制在lname=’Liu’的結果集1上,之後掃描結果集1,產生滿足fname=’Zhiqun’的結果集2,再掃描結果集2,找到 age=26的結果集3,即最終結果。
由 於建立了lname列的索引,與執行表的完全掃描相比,效率提高了很多,但我們要求掃描的記錄數量仍舊遠遠超過了實際所需 要的。雖然我們可以刪除lname列上的索引,再建立fname或者age 列的索引,但是,不論在哪個列上建立索引搜尋效率仍舊相似。
2.多列索引: ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age); 為了提高搜尋效率,我們需要考慮運用多列索引,由於索引檔案以B-Tree格式儲存,所以我們不用掃描任何記錄,即可得到最終結果。
注:在mysql中執行查詢時,只能使用一個索引,如果我們在lname,fname,age上分別建索引,執行查詢時,只能使用一個索引,mysql會選擇一個最嚴格(獲得結果集記錄數最少)的索引。
3.最左字首:顧名思義,就是最左優先,上例中我們建立了lname_fname_age多列索引,相當於建立了(lname)單列索引,(lname,fname)組合索引以及(lname,fname,age)組合索引。
注:在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。
拓展:在網上看到一個關於最左字首原則提出這麼一個例子。
多列欄位做索引,state/city/zipCode,想要索引生效的話,只能使用如下的組合 state/city/zipCode state/city state 其他方式(如city,city/zipCode),則索引不會生效 這種現象是怎麼導致的?和索引的儲存方式有關嗎?
本人頁參考了下其他網友的觀點,個人認為,所謂最左字首原則就是先要看第一列,在第一列滿足的條件下再看左邊第二列,以此類推。有位網友描述得很形象: 你可以認為聯合索引是闖關遊戲的設計
例如你這個聯合索引是state/city/zipCode
那麼state就是第一關 city是第二關, zipCode就是第三關
你必須匹配了第一關,才能匹配第二關,匹配了第一關和第二關,才能匹配第三關
你不能直接到第二關的
索引的格式就是第一層是state,第二層才是city
索引是因為B+樹結構 所以查詢快 如果單看第三列 是非排序的。 多列索引是先按照第一列進行排序,然後在第一列排好序的基礎上再對第二列排序,如果沒有第一列的話,直接訪問第二列,那第二列肯定是無序的,直接訪問後面的列就用不到索引了。 所以如果不是在前面列的基礎上而是但看後面某一列,索引是失效的。大家有不同的觀點可以提出,這是個人理解的觀點。
sql優化