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

Mysql的索引優(yōu)化原則詳解

 更新時(shí)間:2025年12月16日 10:43:53   作者:小吳學(xué)不廢Java  
本文詳細(xì)介紹了MySQL索引優(yōu)化原則,包括最佳左前綴法則、不要在索引列上做任何計(jì)算、避免使用范圍條件、避免使用特定運(yùn)算符等,通過這些原則,可以提高查詢效率,避免全表掃描,感興趣的朋友跟隨小編一起看看吧
  • 創(chuàng)建數(shù)據(jù)庫(kù)、表,插入數(shù)據(jù)
create database idx_optimize character set 'utf8';
CREATE TABLE users(
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_name VARCHAR(20) NOT NULL COMMENT '姓名',
  user_age INT NOT NULL DEFAULT 0 COMMENT '年齡',
  user_level VARCHAR(20) NOT NULL COMMENT '用戶等級(jí)',
  reg_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注冊(cè)時(shí)間'
);
INSERT INTO users(user_name,user_age,user_level,reg_time)
VALUES('tom',17,'A',NOW()),('jack',18,'B',NOW()),('lucy',18,'C',NOW());
  • 創(chuàng)建聯(lián)合索引
ALTER TABLE users ADD INDEX idx_nal (user_name,user_age,user_level) USING BTREE;

2.優(yōu)化原則詳解

1)最佳左前綴法則

最佳左前綴法則: 如果創(chuàng)建的是聯(lián)合索引,就必須遵守這個(gè)法則,當(dāng)使用聯(lián)合索引時(shí),where后面條件需要從索引的最左前開始使用。

  • 場(chǎng)景1: 按照索引字段順序使用,三個(gè)字段都使用了索引,沒有問題
EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
AND user_age = 17 AND user_level = 'A';

  • 場(chǎng)景2: 直接跳過user_name使用索引字段,索引無效,未使用到索引。
EXPLAIN SELECT * FROM users WHERE user_age = 17 AND user_level = 'A';

  • 場(chǎng)景3: 不按照創(chuàng)建聯(lián)合索引的順序,使用索引
EXPLAIN SELECT * FROM users WHERE 
user_age = 17 AND user_name = 'tom' AND user_level = 'A';

where后面查詢條件順序是 user_age、user_level、user_name與我們創(chuàng)建的索引順序user_name、user_age、user_level不一致,為什么還是使用了索引,原因是因?yàn)镸ySql底層優(yōu)化器對(duì)其進(jìn)行了優(yōu)化。

  • 最佳左前綴底層原理
  1. MySQL創(chuàng)建聯(lián)合索引的時(shí)候要遵守一個(gè)規(guī)則: 首先會(huì)對(duì)聯(lián)合索引最左邊的字段進(jìn)行排序,再在第一個(gè)字段的基礎(chǔ)之上對(duì)第二個(gè)字段進(jìn)行排序。

所以: 最佳左前綴原則其實(shí)是和B+樹的結(jié)構(gòu)有關(guān)系, 最左字段肯定是有序的, 第二個(gè)字段則是無序的(聯(lián)合索引的排序方式是: 先按照第一個(gè)字段進(jìn)行排序,如果第一個(gè)字段相等再根據(jù)第二個(gè)字段排序). 所以如果直接使用第二個(gè)字段 user_age 通常是使用不到索引的.

2) 不要在索引列上做任何計(jì)算

不要在索引列上做任何操作,比如計(jì)算、使用函數(shù)、自動(dòng)或手動(dòng)進(jìn)行類型轉(zhuǎn)換,會(huì)導(dǎo)致索引失效,從而使查詢轉(zhuǎn)向全表掃描。

  • 插入數(shù)據(jù)
INSERT INTO users(user_name,user_age,user_level,reg_time) VALUES('11223344',22,'D',NOW());
  • 場(chǎng)景1: 使用系統(tǒng)函數(shù) left()函數(shù),對(duì)user_name進(jìn)行操作
EXPLAIN SELECT * FROM users WHERE LEFT(user_name, 6) = '112233';

場(chǎng)景2: 字符串不加單引號(hào) (隱式類型轉(zhuǎn)換)

varchar類型的字段,在查詢的時(shí)候不加單引號(hào),就需要進(jìn)行隱式轉(zhuǎn)換, 導(dǎo)致索引失效,轉(zhuǎn)向全表掃描。

EXPLAIN SELECT * FROM users WHERE 

3) 范圍之后全失效

范圍之后全失效: where條件中如果有范圍條件,并且范圍條件之后還有其他條件.

  • 場(chǎng)景1: 條件單獨(dú)使用user_name時(shí), type=ref, key_len=62
-- 條件只有一個(gè) user_name
EXPLAIN SELECT * FROM users WHERE user_name = 'tom';

場(chǎng)景2: 條件增加一個(gè) user_age ( 使用常量等值) ,type= ref , key_len = 66

EXPLAIN SELECT * FROM users WHERE user_name = 'tom' AND user_age = 17;

場(chǎng)景3: 使用全值匹配, type = ref , key_len = 128 , 索引都利用上了.

EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
AND user_age = 17 AND user_level = 'A';

場(chǎng)景4: 使用范圍條件時(shí), avg > 17 , type = range , key_len = 66 , 與場(chǎng)景3 比較,可以發(fā)現(xiàn) user_level 索引沒有用上.

-----使用范圍條件  user_age>17  ,user_level索引就失效了
EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
AND user_age > 17 AND user_level = 'A';

4) 避免使用 is null 、 is not null、!= 、or

  • 使用 is null 會(huì)使索引失效
EXPLAIN SELECT * FROM users WHERE user_name IS NULL;
---Impossible where: 表示where條件不成立,不能返回任何的行

  • 使用 is not null 會(huì)使索引失效
EXPLAIN SELECT * FROM users WHERE user_name IS NOT NULL;  ---全表掃描

  • 使用 !=or 會(huì)使索引失效
EXPLAIN SELECT * FROM users WHERE user_name != 'tom';
EXPLAIN SELECT * FROM users WHERE user_name = 'tom' or user_name = 'jack';

5) like以%開頭會(huì)使索引失效

like查詢?yōu)榉秶樵儯?出現(xiàn)在左邊,則索引失效。%出現(xiàn)在右邊索引未失效.

  • 場(chǎng)景1: 兩邊都有% 或者 字段右邊有%,索引都會(huì)失效
EXPLAIN SELECT * FROM users WHERE user_name LIKE '%tom%';
EXPLAIN SELECT * FROM users WHERE user_name LIKE '%tom';

對(duì)比場(chǎng)景1可以知道, 通過使用覆蓋索引 type = index,并且 extra = Using index,從全表掃描變成了全索引掃描.

場(chǎng)景2: 字段左邊有%,索引生效

EXPLAIN SELECT * FROM users WHERE user_name LIKE 'tom%';

解決%出現(xiàn)在左邊索引失效的方法

  • 使用覆蓋索引
EXPLAIN SELECT user_name FROM users WHERE user_name LIKE '%jack%';
EXPLAIN SELECT user_name,user_age,user_level FROM users WHERE user_name LIKE '%jack%';

like 失效的原理

  1. %號(hào)在右: 由于B+樹的索引順序,是按照首字母的大小進(jìn)行排序,%號(hào)在右的匹配又是匹配首字母。所以可以在B+樹上進(jìn)行有序的查找,查找首字母符合要求的數(shù)據(jù)。所以有些時(shí)候可以用到索引.
  2. %號(hào)在左: 是匹配字符串尾部的數(shù)據(jù),我們上面說了排序規(guī)則,尾部的字母是沒有順序的,所以不能按照索引順序查詢,就用不到索引.
  3. 兩個(gè)%%號(hào): 這個(gè)是查詢?nèi)我馕恢玫淖帜笣M足條件即可,只有首字母是進(jìn)行索引排序的,其他位置的字母都是相對(duì)無序的,所以查找任意位置的字母是用不上索引的.

索引優(yōu)化原則總結(jié)

  • 最左前綴法則要遵守
  • 索引列上不計(jì)算
  • 范圍之后全失效
  • 覆蓋索引記住用。
  • 不等于、is null、is not null、or導(dǎo)致索引失效。
  • like百分號(hào)加右邊,加左邊導(dǎo)致索引失效,解決方法:使用覆蓋索引。

到此這篇關(guān)于Mysql的索引優(yōu)化原則的文章就介紹到這了,更多相關(guān)mysql索引優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

宜春市| 宿迁市| 应用必备| 都昌县| 洛川县| 台北县| 桦甸市| 三门县| 上栗县| 若尔盖县| 鄂托克旗| 芜湖市| 大姚县| 出国| 孝感市| 潞城市| 晋江市| 福建省| 沽源县| 石首市| 西盟| 马尔康县| 敦化市| 保德县| 广饶县| 丰宁| 吉木萨尔县| 乐山市| 响水县| 淳化县| 东光县| 肥西县| 聊城市| 绥阳县| 仁怀市| 大渡口区| 乐清市| 阳新县| 平潭县| 湖北省| 洞头县|