搞定面試官 - 你可以介紹一下在 MySQL 中,哪些情況下 索引會失效嘛?

大家好,我是程序員啊粥,前邊給大家分享了

以上幾篇都是偏理論知識,從今天開始,我們開始 MySQL 索引實戰內容,具體介紹一下 MySQL 索引的用法。

首先介紹一下索引的相關語法:

索引語法

-- 創建索引
CREATE INDEX indexName ON table_name (column_name);
ALTER table tableName ADD INDEX indexName(columnName);
-- 刪除索引
DROP INDEX [indexName] ON mytable; 

語法還是非常簡單的,沒什麼太多說的,遵循相關語法規定即可,當然你也可以使用相關的一些 MySQL 客戶端管理工具去創建,比如 Navicat 等。

下邊介紹一下具體的一些使用語法:

索引使用

今天的實戰內容以如下表爲例:

CREATE TABLE `tb_item` (
  `id` bigint NOT NULL COMMENT '書籍id,同時也是書籍編號',
  `title` varchar(100) NOT NULL COMMENT '書籍名稱',
  `sell_point` varchar(500) DEFAULT NULL COMMENT '書籍賣點',
  `price` bigint NOT NULL COMMENT '書籍價格,單位爲:分',
  `num` int NOT NULL COMMENT '庫存數量',
  `barcode` varchar(30) DEFAULT NULL COMMENT '書籍條形碼',
  `image` varchar(500) DEFAULT NULL COMMENT '書籍圖片',
  `cid` bigint NOT NULL COMMENT '所屬類目,葉子類目',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '書籍狀態,1-正常,2-下架,3-刪除',
  `created` datetime NOT NULL COMMENT '創建時間',
  `updated` datetime NOT NULL COMMENT '更新時間',
  `upload_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  KEY `status` (`status`),
  KEY `updated` (`updated`),
  KEY `tb_item_title_price_num` (`title`,`price`,`num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='書籍表';

file

InnoDB 索引因爲使用了 B+ 樹數據結構,所以在使用上我們就需要了解這種結構,具體你可以回顧我前邊這篇文章: MySQL InnoDB B+ 樹的索引模型

也正是因爲使用了這種結構,所以在使用上我們需要遵循一些原則,才能讓索引不失效。

最左前綴法則

如果你是建立聯合索引,那麼我們在使用查詢條件的時候,需要從這個索引的最左列開始,並且不跳過索引中的列;如果跳躍某一列,那麼就會造成索引部分失效;比如你建立的聯合索引字段是 (a, b , c),那麼,你的查詢條件就必須是 where a = and b = and c = 這樣的格式(具體 a b c 還是 c b a 的順序不會影響索引,MySQL 優化器會自動優化這種順序);

當然,你如果直接把前綴去掉的話,那整個索引就會失效,不再是部分失效。

比如上述表,我們使用查詢語句爲 explain select * from tb_item where price = 45 and num = 23232 ;

我們建立的索引字段是 title, price, num,但是我們查詢條件直接跳過了 title 這個字段,使用 explain 可以看到這條 SQL 的執行計劃,key 的值是 Null,意味着這句 SQL 沒有利用到索引,而是走了全表掃描。

file

那麼我們最合理的使用,就是使用最左前綴匹配,查詢條件改成這樣:explain select * from tb_item where title = '編譯原理' and price = 45 and num = 23232;

再來看一下執行計劃,我們看到 key 這倆變爲了 tb_item_title_price_num,同時索引長度爲 314 ,證明是使用到了聯合索引 tb_item_title_price_num 的三個完整字段的(關於索引長度的計算方式可以參考這篇文章)

file

索引長度的計算公式:

因爲聯合索引的結構特點, 我們需要確認命中索引 tb_item_title_price_num 是命中了 title 列、price 列,還是 num 列。

想要會分析,就需要掌握索引長度的計算方法了。

1、索引長度公式

  1. 所有的索引字段,如果沒有設置 not null,則需要加一個字節。

  2. 定長字段,int 佔四個字節、date 佔三個字節、char(n) 佔 n 個字符。

  3. 對於變成字段 varchar(n),則有 n 個字符 + 兩個字節。

  4. 不同的字符集,一個字符佔用的字節數不同。latin1 編碼的,一個字符佔用一個字節,gbk 編碼的,一個字符佔用兩個字節,utf8 編碼的,一個字符佔用三個字節,utf8mb4 編碼的,一個字符佔四個字節

  5. 索引長度 char()、varchar() 索引長度的計算公式:

Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列長度 + 1(允許 null) + 2(變長列)

綜上可得:上述 tb_item 表中,使用的 utf8 編碼

所以 title 字段的索引長度是 3 * 100 + 0 + 2 = 302

price 字段的索引長度是 8

num 字段的索引長度是 4

tb_item_title_price_num 索引總共長度是 302 + 8 + 4 = 314

接下來我們修改查詢條件爲 explain select * from tb_item where title = '編譯原理' and num = 23232;

此時 Key len 變爲 302,說明只利用到了 title 的索引,因爲查詢條件跳過了 price 字段,導致部分索引失效。

file

同時 Extra 爲 Using index condition,說明使用了索引,但是需要回表查詢數據。

覆蓋索引

在索引使用過程中,尤其是聯合索引的使用中,我們如何合理的建立索引,再加上合理的查詢條件的話,我們是可以使用到覆蓋索引的,減少回表次數,也就是減少了 IO 次數,可以成倍的提高查詢效率。

下邊我們來演示下使用覆蓋索引的情況,比如使用如下查詢語句:explain select id, title from tb_item where title = '編譯原理' and num = 12000;

file

這個時候我們可以看到 Extra 值爲:Using where; Using index,這意味着這次查詢時使用了索引的,同時因爲要查詢的列已經在索引中可以直接獲取到,所以不需要回表去獲取數據,可以直接在索引中找到需要的字段,這也是一般要求不允許 select * 查詢的原因,因爲這樣的話需要獲取所有字段,沒法利用覆蓋索引來提高效率。

關於執行計劃中 Extra 字段的說明,參考我之前的這篇文文章。

Extra 字段說明:

using index :使用覆蓋索引的時候就會出現 using where:在查找使用索引的情況下,需要回表去查詢所需的數據 using index condition:查找使用了索引,但是需要回表查詢數據 using index ; using where:查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表。

同時,阿里開發規範中對於索引規範的建議,也是有對於覆蓋索引的說明的:

file

範圍查詢

在實際開發中,範圍查詢也是我們需要經常使用的一個東西,比如統計過去 3 天、過去 7 天的用戶量等等。

但這個時候有個問題需要注意,那就是在使用範圍查詢的時候,範圍查詢右邊的列索引會失效。

比如下圖中的幾種查詢條件,我們可以看到寫法上差不多的,但是最後索引字段的長度是完全不一樣的。

file

其中第一條 select id from tb_item where title = '編譯原理' and price = 56 and num = 10000,是我們常用的等值查詢,這在上一步最左前綴的時候已經說了,肯定是可以完整用到索引的,執行計劃也驗證了我們的結論。

第二條查詢語句 select id from tb_item where title = '編譯原理' and price > 56 and num = 10000, 我們使用了範圍查詢,這個時候可以看到 key_len 變成了 310,這說明部分索引失效了,也就是範圍查詢右邊的列,num 這個列的索引失效了。

第三條查詢語句select id from tb_item where title = '編譯原理' and price >= 56 and num = 10000,是一種很好的規避這種索引失效的一種手段,在業務允許的情況下我們可以使用大於等於或者小於等於來代替大於或者小於,這種情況下是可以完整使用到索引的。

索引列運算

我遇到過很多開發人員,會在 SQL 中摻雜運算,這在你的數據量不大的前提下,確實可以爲你提供方便,但是一旦你的數據量起來之後,你如果在索引列上做計算,這會直接導致索引的失效,進而引發全表掃描。

因爲 MySQL 在做索引的時候是對你的字段值本身做索引,而不是對你運算後的值做索引,你可以回顧下關於 B+ 樹的索引模型]

所以我們在實際使用中需要徹底避免在索引列上做計算,因爲沒有任何一個理由支持我們必須要這麼做。

比如這個查詢語句 explain select * from tb_item where substring(title,4, 4) = '組成原理';

看一下它的執行計劃:

file

可以看到是完全沒有用到索引的,直接開始全表掃描,你試想一下,假如你的表就幾十上百萬數據,這一個全表掃描下去,你怕是半夜都不敢睡覺吧。

字符串不加引號

MySQL 在索引查詢中,會自動的進行的字段類型轉換,如果我們對於一個數字格式的字符串字段,在查詢的時候沒有用單引號,那麼會觸發 MySQL 查詢優化器的類型自動轉換。

比如你有張表存的是手機號,字段叫 phone,然後針對查詢語句 select id from tb_user where phone = 1888888888,那怕你在 phone 字段上額外建了索引,它也是不會走索引的。

因爲這條語句在查詢優化器的處理下會變成 select id from tb_user where cast(phone as signed int) = 1888888888 去執行。

這個時候因爲對索引列做了函數運算,就導致了索引的失效。

模糊查詢

關於模糊查詢,這個也就等同於最左前綴原則,你如果是在字段的頭部位置進行模糊搜索的話,首先不遵循最左前綴匹配原則,那索引自然就失效了。

反之,如果是尾部字段進行模糊匹配的話,那麼索引還是同樣生效的。

因此,我們真的需要模糊搜索功能的話,最佳的方式是使用搜索引擎,而不是在 MySQL 中直接 like 查詢。

or 連接條件

用 or 分割開的條件,如果 or 前的條件列中有索引,而後面的列中沒有索引,那麼索引會失效,不管是這兩個字段中的任何一個索引,都會失效。

比如我們這張表 tb_item 表中 barcode 列沒有索引,使用如下查詢語句

explain select id, title from tb_item where title = '編譯原理' or barcode = '202457815';

file

通過執行計劃可以看到,索引全部失效了。

反之,如果 or 兩邊的字段都有索引,則索引依然可以生效

explain select id, title from tb_item where title = '編譯原理' or price = 128;

file

數據分佈影響

其實前邊說了好幾個原則,但是在具體使用中,我們還是需要用實際情況來分析,首先如何選擇索引是 MySQL 自己做的事情,如果 MySQL 評估使用索引會比全表更慢,則不使用索引。

那麼,什麼情況下它評估使用索引還不如直接全表掃描呢?

常見的一種情況是表中的數據分析分佈,如果這個字段的值區分度不夠明顯,那麼 MySQL 極有可能進行全表掃描。

比如使用這條查詢語句 explain select * from tb_item where title = '高等數學';

file

執行計劃顯示可以看到是沒有走索引的,按理來說我們建立了聯合索引 tb_item_title_price_num (title,price,num) ,同時也遵循最左前綴匹配原則,是可以走到索引的,可現在的執行計劃說沒有用到索引。

接下來我們修改查詢條件爲:explain select * from tb_item where title = '編譯原理';

file

可以看到同樣的查詢語句,只不過是值不同,就會造成一個索引生效,一個索引失效,究其原因,是因爲表中 title 爲'高等數學'的數據佔比太多,MySQL 判斷與其走索引還不如直接全表掃描,所以索引失效了。

file

可以看到,表中總共 841 行數據,其中高等數據就佔了 803 條。

前綴索引

前邊我有篇文章提到過,InnoDB 引擎對於索引的字段長度是有限制的,TODO,所以在我們遇到字段類型過長的時候,可以截取一部分來建立索引,從而節約索引空間,提高查詢效率。

關於前綴索引,我們需要明確以下幾年內容:

  1. 創建索引,指定索引長度語法:create index idx_xxx on table_name(column(n))
  2. 前綴長度的選擇:可以根據索引的選擇性來決定,選擇性越高則查詢效率越高,唯一索引的選擇性是 1 ,這是最好的索引選擇性,性能也是最好的。
  3. 索引列區分度查詢,類似如下
    • select count(distinct email)/count(*) from tb_user;
    • select count(distinct substring(email,1,5))/cont(*) from tb_user
  4. 前綴索引的好處:
    • 使用前綴索引,定義好長度,就可以做到既節省空間,又不用額外增加太多的查詢成本。
  5. 前綴索引的缺點
    • 使用前綴索引就用不上覆蓋索引對查詢性能的優化了,這也是你在選擇是否使用前綴索引時需要考慮的一個因素

阿里開發規範中對於前綴索引的規約說明

file

今天的內容到此就要結束了,簡單總結一下:

關於索引失效和索引使用原則,需要遵循最最前綴匹配原則,這是 B+ 樹的索引模型決定的。此外,不當的使用方式,會造成索引的部分失效,比如範圍查詢、字符串不加引號,使用索引列字段進行函數運算以及使用 Or 查詢條件時其中某個字段沒有索引等等。

內容比較多,而且是偏實戰型的,雖然我提供了具體的示例,但還是希望你能自己動手操作一遍,這樣才能記得更牢靠,下次看見面試官你就直接糊他臉上。------------恢復內容開始------------
大家好,我是程序員啊粥,前邊給大家分享了

以上幾篇都是偏理論知識,從今天開始,我們開始 MySQL 索引實戰內容,具體介紹一下 MySQL 索引的用法。

首先介紹一下索引的相關語法:

索引語法

-- 創建索引
CREATE INDEX indexName ON table_name (column_name);
ALTER table tableName ADD INDEX indexName(columnName);
-- 刪除索引
DROP INDEX [indexName] ON mytable; 

語法還是非常簡單的,沒什麼太多說的,遵循相關語法規定即可,當然你也可以使用相關的一些 MySQL 客戶端管理工具去創建,比如 Navicat 等。

下邊介紹一下具體的一些使用語法:

索引使用

今天的實戰內容以如下表爲例:

CREATE TABLE `tb_item` (
  `id` bigint NOT NULL COMMENT '書籍id,同時也是書籍編號',
  `title` varchar(100) NOT NULL COMMENT '書籍名稱',
  `sell_point` varchar(500) DEFAULT NULL COMMENT '書籍賣點',
  `price` bigint NOT NULL COMMENT '書籍價格,單位爲:分',
  `num` int NOT NULL COMMENT '庫存數量',
  `barcode` varchar(30) DEFAULT NULL COMMENT '書籍條形碼',
  `image` varchar(500) DEFAULT NULL COMMENT '書籍圖片',
  `cid` bigint NOT NULL COMMENT '所屬類目,葉子類目',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '書籍狀態,1-正常,2-下架,3-刪除',
  `created` datetime NOT NULL COMMENT '創建時間',
  `updated` datetime NOT NULL COMMENT '更新時間',
  `upload_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  KEY `status` (`status`),
  KEY `updated` (`updated`),
  KEY `tb_item_title_price_num` (`title`,`price`,`num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='書籍表';

file

InnoDB 索引因爲使用了 B+ 樹數據結構,所以在使用上我們就需要了解這種結構,具體你可以回顧我前邊這篇文章:MySQL InnoDB 索引模型。

也正是因爲使用了這種結構,所以在使用上我們需要遵循一些原則,才能讓索引不失效。

最左前綴法則

如果你是建立聯合索引,那麼我們在使用查詢條件的時候,需要從這個索引的最左列開始,並且不跳過索引中的列;如果跳躍某一列,那麼就會造成索引部分失效;比如你建立的聯合索引字段是 (a, b , c),那麼,你的查詢條件就必須是 where a = and b = and c = 這樣的格式(具體 a b c 還是 c b a 的順序不會影響索引,MySQL 優化器會自動優化這種順序);

當然,你如果直接把前綴去掉的話,那整個索引就會失效,不再是部分失效。

比如上述表,我們使用查詢語句爲 explain select * from tb_item where price = 45 and num = 23232 ;

我們建立的索引字段是 title, price, num,但是我們查詢條件直接跳過了 title 這個字段,使用 explain 可以看到這條 SQL 的執行計劃,key 的值是 Null,意味着這句 SQL 沒有利用到索引,而是走了全表掃描。

file

那麼我們最合理的使用,就是使用最左前綴匹配,查詢條件改成這樣:explain select * from tb_item where title = '編譯原理' and price = 45 and num = 23232;

再來看一下執行計劃,我們看到 key 這倆變爲了 tb_item_title_price_num,同時索引長度爲 314 ,證明是使用到了聯合索引 tb_item_title_price_num 的三個完整字段的(關於索引長度的計算方式可以參考這篇文章)

file

索引長度的計算公式:

因爲聯合索引的結構特點, 我們需要確認命中索引 tb_item_title_price_num 是命中了 title 列、price 列,還是 num 列。

想要會分析,就需要掌握索引長度的計算方法了。

1、索引長度公式

  1. 所有的索引字段,如果沒有設置 not null,則需要加一個字節。

  2. 定長字段,int 佔四個字節、date 佔三個字節、char(n) 佔 n 個字符。

  3. 對於變成字段 varchar(n),則有 n 個字符 + 兩個字節。

  4. 不同的字符集,一個字符佔用的字節數不同。latin1 編碼的,一個字符佔用一個字節,gbk 編碼的,一個字符佔用兩個字節,utf8 編碼的,一個字符佔用三個字節,utf8mb4 編碼的,一個字符佔四個字節

  5. 索引長度 char()、varchar() 索引長度的計算公式:

Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列長度 + 1(允許 null) + 2(變長列)

綜上可得:上述 tb_item 表中,使用的 utf8 編碼

所以 title 字段的索引長度是 3 * 100 + 0 + 2 = 302

price 字段的索引長度是 8

num 字段的索引長度是 4

tb_item_title_price_num 索引總共長度是 302 + 8 + 4 = 314

接下來我們修改查詢條件爲 explain select * from tb_item where title = '編譯原理' and num = 23232;

此時 Key len 變爲 302,說明只利用到了 title 的索引,因爲查詢條件跳過了 price 字段,導致部分索引失效。

file

同時 Extra 爲 Using index condition,說明使用了索引,但是需要回表查詢數據。

覆蓋索引

在索引使用過程中,尤其是聯合索引的使用中,我們如何合理的建立索引,再加上合理的查詢條件的話,我們是可以使用到覆蓋索引的,減少回表次數,也就是減少了 IO 次數,可以成倍的提高查詢效率。

下邊我們來演示下使用覆蓋索引的情況,比如使用如下查詢語句:explain select id, title from tb_item where title = '編譯原理' and num = 12000;

file

這個時候我們可以看到 Extra 值爲:Using where; Using index,這意味着這次查詢時使用了索引的,同時因爲要查詢的列已經在索引中可以直接獲取到,所以不需要回表去獲取數據,可以直接在索引中找到需要的字段,這也是一般要求不允許 select * 查詢的原因,因爲這樣的話需要獲取所有字段,沒法利用覆蓋索引來提高效率。

關於執行計劃中 Extra 字段的說明,參考我之前的這篇文文章。

Extra 字段說明:

using index :使用覆蓋索引的時候就會出現 using where:在查找使用索引的情況下,需要回表去查詢所需的數據 using index condition:查找使用了索引,但是需要回表查詢數據 using index ; using where:查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表。

同時,阿里開發規範中對於索引規範的建議,也是有對於覆蓋索引的說明的:

file

範圍查詢

在實際開發中,範圍查詢也是我們需要經常使用的一個東西,比如統計過去 3 天、過去 7 天的用戶量等等。

但這個時候有個問題需要注意,那就是在使用範圍查詢的時候,範圍查詢右邊的列索引會失效。

比如下圖中的幾種查詢條件,我們可以看到寫法上差不多的,但是最後索引字段的長度是完全不一樣的。

file

其中第一條 select id from tb_item where title = '編譯原理' and price = 56 and num = 10000,是我們常用的等值查詢,這在上一步最左前綴的時候已經說了,肯定是可以完整用到索引的,執行計劃也驗證了我們的結論。

第二條查詢語句 select id from tb_item where title = '編譯原理' and price > 56 and num = 10000, 我們使用了範圍查詢,這個時候可以看到 key_len 變成了 310,這說明部分索引失效了,也就是範圍查詢右邊的列,num 這個列的索引失效了。

第三條查詢語句select id from tb_item where title = '編譯原理' and price >= 56 and num = 10000,是一種很好的規避這種索引失效的一種手段,在業務允許的情況下我們可以使用大於等於或者小於等於來代替大於或者小於,這種情況下是可以完整使用到索引的。

索引列運算

我遇到過很多開發人員,會在 SQL 中摻雜運算,這在你的數據量不大的前提下,確實可以爲你提供方便,但是一旦你的數據量起來之後,你如果在索引列上做計算,這會直接導致索引的失效,進而引發全表掃描。

因爲 MySQL 在做索引的時候是對你的字段值本身做索引,而不是對你運算後的值做索引,你可以回顧下關於 B+ 樹的索引模型,TODO,

所以我們在實際使用中需要徹底避免在索引列上做計算,因爲沒有任何一個理由支持我們必須要這麼做。

比如這個查詢語句 explain select * from tb_item where substring(title,4, 4) = '組成原理';

看一下它的執行計劃:

file

可以看到是完全沒有用到索引的,直接開始全表掃描,你試想一下,假如你的表就幾十上百萬數據,這一個全表掃描下去,你怕是半夜都不敢睡覺吧。

字符串不加引號

MySQL 在索引查詢中,會自動的進行的字段類型轉換,如果我們對於一個數字格式的字符串字段,在查詢的時候沒有用單引號,那麼會觸發 MySQL 查詢優化器的類型自動轉換。

比如你有張表存的是手機號,字段叫 phone,然後針對查詢語句 select id from tb_user where phone = 1888888888,那怕你在 phone 字段上額外建了索引,它也是不會走索引的。

因爲這條語句在查詢優化器的處理下會變成 select id from tb_user where cast(phone as signed int) = 1888888888 去執行。

這個時候因爲對索引列做了函數運算,就導致了索引的失效。

模糊查詢

關於模糊查詢,這個也就等同於最左前綴原則,你如果是在字段的頭部位置進行模糊搜索的話,首先不遵循最左前綴匹配原則,那索引自然就失效了。

反之,如果是尾部字段進行模糊匹配的話,那麼索引還是同樣生效的。

因此,我們真的需要模糊搜索功能的話,最佳的方式是使用搜索引擎,而不是在 MySQL 中直接 like 查詢。

or 連接條件

用 or 分割開的條件,如果 or 前的條件列中有索引,而後面的列中沒有索引,那麼索引會失效,不管是這兩個字段中的任何一個索引,都會失效。

比如我們這張表 tb_item 表中 barcode 列沒有索引,使用如下查詢語句

explain select id, title from tb_item where title = '編譯原理' or barcode = '202457815';

file

通過執行計劃可以看到,索引全部失效了。

反之,如果 or 兩邊的字段都有索引,則索引依然可以生效

explain select id, title from tb_item where title = '編譯原理' or price = 128;

file

數據分佈影響

其實前邊說了好幾個原則,但是在具體使用中,我們還是需要用實際情況來分析,首先如何選擇索引是 MySQL 自己做的事情,如果 MySQL 評估使用索引會比全表更慢,則不使用索引。

那麼,什麼情況下它評估使用索引還不如直接全表掃描呢?

常見的一種情況是表中的數據分析分佈,如果這個字段的值區分度不夠明顯,那麼 MySQL 極有可能進行全表掃描。

比如使用這條查詢語句 explain select * from tb_item where title = '高等數學';

file

執行計劃顯示可以看到是沒有走索引的,按理來說我們建立了聯合索引 tb_item_title_price_num (title,price,num) ,同時也遵循最左前綴匹配原則,是可以走到索引的,可現在的執行計劃說沒有用到索引。

接下來我們修改查詢條件爲:explain select * from tb_item where title = '編譯原理';

file

可以看到同樣的查詢語句,只不過是值不同,就會造成一個索引生效,一個索引失效,究其原因,是因爲表中 title 爲'高等數學'的數據佔比太多,MySQL 判斷與其走索引還不如直接全表掃描,所以索引失效了。

file

可以看到,表中總共 841 行數據,其中高等數據就佔了 803 條。

前綴索引

前邊我有篇文章提到過,InnoDB 引擎對於索引的字段長度是有限制的,TODO,所以在我們遇到字段類型過長的時候,可以截取一部分來建立索引,從而節約索引空間,提高查詢效率。

關於前綴索引,我們需要明確以下幾年內容:

  1. 創建索引,指定索引長度語法:create index idx_xxx on table_name(column(n))
  2. 前綴長度的選擇:可以根據索引的選擇性來決定,選擇性越高則查詢效率越高,唯一索引的選擇性是 1 ,這是最好的索引選擇性,性能也是最好的。
  3. 索引列區分度查詢,類似如下
    • select count(distinct email)/count(*) from tb_user;
    • select count(distinct substring(email,1,5))/cont(*) from tb_user
  4. 前綴索引的好處:
    • 使用前綴索引,定義好長度,就可以做到既節省空間,又不用額外增加太多的查詢成本。
  5. 前綴索引的缺點
    • 使用前綴索引就用不上覆蓋索引對查詢性能的優化了,這也是你在選擇是否使用前綴索引時需要考慮的一個因素

阿里開發規範中對於前綴索引的規約說明

file

今天的內容到此就要結束了,簡單總結一下:

關於索引失效和索引使用原則,需要遵循最最前綴匹配原則,這是 B+ 樹的索引模型決定的。此外,不當的使用方式,會造成索引的部分失效,比如範圍查詢、字符串不加引號,使用索引列字段進行函數運算以及使用 Or 查詢條件時其中某個字段沒有索引等等。

內容比較多,而且是偏實戰型的,雖然我提供了具體的示例,但還是希望你能自己動手操作一遍,這樣才能記得更牢靠,下次看見面試官你就直接糊他臉上。

我是程序員啊粥,關注我,我們一起在技術海洋中向上生長。
------------恢復內容結束------------

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