最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL細數(shù)發(fā)生索引失效的情況

 更新時間:2022年07月13日 08:55:50   作者:少年.  
本文主要介紹了MySQL導致索引失效的幾種情況,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

索引的存儲結構

首先了解一下索引的存儲結構,知道了索引的存儲結構,才方便我們更好地理解索引失效的問題。

索引的存儲結構跟MySQL的存儲引擎有關,存儲引擎的不同采用的結構也會不同。

MySQL默認的存儲引擎InnoDB采用B+Tree作為索引的數(shù)據(jù)結構,在創(chuàng)建表時,InnoDB會默認創(chuàng)建一個主鍵索引,這是一個聚簇索引,其他索引都屬于二級索引。

MyISAM存儲引擎在創(chuàng)建表時,默認是用的是B+樹索引。

雖然和InnoDB一樣都支持B+樹索引,但是他們存儲數(shù)據(jù)的方式不同;

InnoDB是聚簇索引(B+樹索引的葉子結點保存數(shù)據(jù)本身)

MyISAM是非聚集索引(B+樹的葉子結點保存數(shù)據(jù)的物理地址)

如下圖所示:

InnoDB存儲引擎可以分為【聚簇索引】和【二級索引】,它們的區(qū)別在于聚簇索引的葉子結點存放的是實際數(shù)據(jù),所有完整的數(shù)據(jù)都存放在聚簇索引的葉子結點,二級索引的葉子結點存放的是主鍵值。

在使用二級索引字段作為查詢條件,查詢數(shù)據(jù)在聚簇索引上的時候,

會先根據(jù)條件在二級索引上找到對應的葉子結點得到主鍵值,

再根據(jù)主鍵值去聚簇索引上找到對應的葉子結點然后查詢到對應的數(shù)據(jù),

這個過程叫回表

使用二級索引作為查詢條件,查詢的數(shù)據(jù)在二級索引的葉子結點上的時候,那么只需找到二級索引的B+樹對應的葉子結點,讀取數(shù)據(jù),這個過程叫覆蓋索引

上面這些查詢條件都用到了索引列,但并不表示用到索引列索引就一定會生效,我們再來看一看索引失效的情況

不合理的模糊查詢條件

使用左或左右模糊查詢的時候,也就是like "%張"like "%張%"這兩種模糊查詢方式都會導致索引失效

因為B+樹是根據(jù)索引值進行排列的,前綴不確定的時候可能是,“小張”,"二張"之類的所有的情況,就只能通過全表掃描的方式來查詢

對索引使用函數(shù)

例如:SELECT * FROM sys_user WHERE LENGTH(user_id) = 3 ;

因為索引保存的是索引字段的原始值,而不是經(jīng)過函數(shù)計算后的值,所以使用函數(shù)的時候就不會走索引了

不過從MySQL8.0開始,索引特性增加了函數(shù)索引,也就是針對該函數(shù)計算后的值建立一個索引,這樣就可以通過掃描索引來查詢數(shù)據(jù)了;

alter table t_user add key idx_name_length ((length(name)));

對索引進行表達式計算

例如:select * from sys_user where user_id+1 =3;

但是如果是SELECT * FROM sys_user WHERE user_id = 1+1 ;這樣的不在索引字段上進行計算,就又會走索引了

原因跟對索引使用函數(shù)差不多,索引保存的是索引字段的原始值,而不是運算后的值,所以無法走索引

對索引使用隱式轉換

這里的phone字段是二級索引,且是varchar類型的

使用整型作為查詢參數(shù)的時候,執(zhí)行計劃中type為ALL,也就是通過全表掃描查詢的,但如果是字符串類型,還是走索引查詢的

我們再看一個例子

這里user_id是bigint類型,但是使用字符串作為查詢參數(shù)還是走了索引的

為什么第一個例子導致了索引失效,而第二個不會呢?

這里就要了解一下MySQL的字符轉換規(guī)則了,看是數(shù)字轉字符串,還是字符串轉數(shù)字

我們可以用select "10">9來測試一下

如果是數(shù)字轉字符串,那么就相當于select "10">"9"結果應該是0

如果是字符串轉數(shù)字,那么就相當于select 10>9,結果是1

在MySQL中的執(zhí)行結果如下:

這就說明,MySQL在遇到數(shù)字與字符串的比較的時候,會自動把字符串轉換為數(shù)字,然后進行比較

也就是說,在第一個例子中

SELECT * FROM sys_user WHERE phone = 18200000000 ;

相當于

SELECT * FROM sys_user WHERE CAST(phone AS UNSIGNED) = 18200000000 ;

這就在索引字段上使用了函數(shù),所以導致索引失效

而在第二個例子中

SELECT * FROM sys_user WHERE user_id = "1" ;

相當于

SELECT * FROM sys_user WHERE user_id = CAST("1" AS UNSIGNED) ;

函數(shù)式作用在查詢參數(shù)上的,并沒有作用在索引字段上,所以還是走索引的

聯(lián)合索引非最左匹配

多個普通字段組合在一起創(chuàng)建的索引叫做聯(lián)合索引(組合索引)

在使用聯(lián)合索引的時候,一定要注意順序問題,聯(lián)合索引的使用需要遵循最左匹配原則,也就是按照最左優(yōu)先的方式進行索引匹配。

例如,創(chuàng)建了一個(a,b,c)聯(lián)合索引,那么如果查詢條件是一下幾種,就可以匹配上聯(lián)合索引

where a = 1
where a = 1 and b = 2
where a = 1 and b = 2 and c = 3

需要注意的是,因為有查詢優(yōu)化器,所以a字段在where子句中的順序不重要

但是必須要有a字段,如果像下面幾種,因為不符合最左匹配原則,就無法匹配上聯(lián)合索引,聯(lián)合索引就會失效:

where b = 2
where c = 3
where b = 2 and c = 3

還有一個比較特殊的查詢條件:where a = 1 and c = 3

在MySQL5.5的話,前面的a 會走索引,在聯(lián)合索引找到主鍵值,然后回表,到主鍵索引讀取數(shù)據(jù)行,然后在比對c字段的值

在MySQL5.6之后,有一個索引下推的功能,

下推就是將部分上層(服務層)負責的事情,交給了下層(引擎層)處理

存儲引擎直接在聯(lián)合索引里按照c=3過濾,按照過濾后的數(shù)據(jù)在進行回表掃描,減少了回表的次數(shù),從而提升了性能

在執(zhí)行計劃中Extra = Using index condition就表示使用了索引下推

聯(lián)合索引不遵循最左匹配原則的原因:在聯(lián)合索引中,數(shù)據(jù)按照第一列索引進行排序,第一列數(shù)據(jù)相同時,才會按照第二列進行排序,以此類推,所以直接使用第二列進行查詢的時候,聯(lián)合索引就會失效

where子句中的or

where子句中or的條件列有不是索引列會導致索引失效

例如:下圖中id是索引列,email不是索引列,從執(zhí)行計劃來看,進行了全文掃描并沒有使用到索引

因為or關鍵字只滿足一個條件就可以,因此只要有一個列不是索引列,其他索引列也就沒有意義了,就會進行全表掃描

在email列上建立索引之后,可以看到執(zhí)行計劃中使用到了兩個索引

type = index_merge表示對id 和email都進行了掃描,然后進行了合并

總結

導致索引失效的情況有:

不合理的使用模糊查詢:like "%張"like %張%

對索引列使用函數(shù)

對索引使用表達式計算

對索引使用隱式轉換,這三個都是引起了索引列值的變化導致索引失效

聯(lián)合索引非最左匹配

where子句中or條件列沒有使用索引

到此這篇關于MySQL細數(shù)發(fā)生索引失效的情況的文章就介紹到這了,更多相關MySQL索引失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MySQL 在觸發(fā)器里中斷記錄的插入或更新?

    MySQL 在觸發(fā)器里中斷記錄的插入或更新?

    MySQL 不象其它有些數(shù)據(jù)庫可以在觸發(fā)器中拋出異常來中斷當然觸發(fā)器的執(zhí)行以阻止相應的SQL語句的執(zhí)行。在MySQL的目錄版本中還無法直接拋出異常。這樣我們?nèi)绾螌崿F(xiàn)呢?
    2009-07-07
  • 解決mysql創(chuàng)建數(shù)據(jù)庫后出現(xiàn):Access denied for user ''root''@''%'' to database ''xxx''的問題

    解決mysql創(chuàng)建數(shù)據(jù)庫后出現(xiàn):Access denied for user ''root''@''%'' to dat

    這篇文章主要給大家介紹了如何解決mysql在創(chuàng)建數(shù)據(jù)庫后出現(xiàn):Access denied for user 'root'@'%' to database 'xxx'的錯誤提示,文中介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • MACOS中忘記MySQL root密碼的解決方案

    MACOS中忘記MySQL root密碼的解決方案

    這篇文章主要向大家講述的是在MAC系統(tǒng)中MySQL重設root密碼的實際操作步驟,在實際操作中忘記MySQL root密碼時常會發(fā)生的,下面就是本教程的詳細內(nèi)容介紹。
    2017-03-03
  • MySQL系列之四 SQL語法

    MySQL系列之四 SQL語法

    SQL是一種特殊目的的編程語言,是一種數(shù)據(jù)庫查詢和程序設計語言,用于存取數(shù)據(jù)以及查詢、更新和管理關系數(shù)據(jù)庫系統(tǒng),這篇文章主要給大家介紹了SQL語法的相關資料,需要的朋友可以參考下
    2021-07-07
  • mysql視圖原理與用法實例小結

    mysql視圖原理與用法實例小結

    這篇文章主要介紹了mysql視圖原理與用法,結合實例形式分析了mysql視圖的概念、原理、創(chuàng)建、使用方法及相關注意事項,需要的朋友可以參考下
    2018-04-04
  • MySQL報錯 table “xxx” doesn‘t exit的解決

    MySQL報錯 table “xxx” doesn‘t exit的解決

    本文主要介紹了MySQL報錯 table “xxx” doesn‘t exit的解決,主要原因是英文字母大小寫敏感導致,下面就來介紹一下解決方法,感興趣的可以了解一下
    2023-10-10
  • 詳解MySQL中varchar和int隱式轉換的注意事項

    詳解MySQL中varchar和int隱式轉換的注意事項

    這篇文章主要為大家詳細介紹了MySQL中varchar和int隱式轉換的注意事項,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-12-12
  • mysql 5.7.17 免安裝版配置方法圖文教程(windows10)

    mysql 5.7.17 免安裝版配置方法圖文教程(windows10)

    這篇文章主要為大家詳細介紹了windows10下mysql 5.7.17 免安裝版配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • MySQL通過DQL實現(xiàn)對數(shù)據(jù)庫數(shù)據(jù)的條件查詢

    MySQL通過DQL實現(xiàn)對數(shù)據(jù)庫數(shù)據(jù)的條件查詢

    這篇文章給大家介紹了MySQL如何通過DQL進行數(shù)據(jù)庫數(shù)據(jù)的條件查詢,文中通過代碼示例和圖文結合介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • 驗證mysql是否安裝成功的方法

    驗證mysql是否安裝成功的方法

    在本篇文章里小編給大家分享的是關于驗證mysql是否安裝成功的方法,需要的朋友們可以學習下。
    2020-06-06

最新評論

安新县| 德州市| 宁远县| 噶尔县| 洪江市| 鄂伦春自治旗| 南陵县| 昌平区| 大宁县| 小金县| 井陉县| 嘉祥县| 津市市| 弋阳县| 临夏市| 宁晋县| 保定市| 故城县| 潞城市| 高阳县| 哈密市| 衡阳县| 邛崃市| 名山县| 西华县| 家居| 固阳县| 民乐县| 浏阳市| 太谷县| 富源县| 保靖县| 修武县| 英吉沙县| 神池县| 庆阳市| 枣阳市| 时尚| 海口市| 大埔县| 白银市|