首頁  >  文章  >  資料庫  >  Mysql索引最左前綴的原則是什麼

Mysql索引最左前綴的原則是什麼

PHPz
PHPz轉載
2023-05-28 14:19:063414瀏覽

前言

之所以有這個最左前綴索引

歸根究底是mysql的資料庫結構B 樹

在實際問題中例如

索引index (a,b,c)有三個字段,

使用查詢語句select * from table where c = '1' ,sql語句不會走index索引的

select * from table where b =‘1’ and c ='2' 這個語句也不會走index索引

1.定義

最左前綴匹配原則:在MySQL建立聯合索引時會遵守最左前綴匹配原則,即最左優先,在檢索資料時從聯合索引的最左邊開始匹配

為了更好辨別這種情況,透過建立表格以及索引的情況進行分析

2. 全索引順序

建立一張表,建立一個聯合索引,如果順序顛倒,其實還是可以識別的,但是一定要有它的全部部分

建立表

CREATE TABLE staffs(
	id INT PRIMARY KEY AUTO_INCREMENT,
	`name` VARCHAR(24) NOT NULL DEFAULT'' COMMENT'姓名',
	`age` INT NOT NULL DEFAULT 0 COMMENT'年龄',
	`pos` VARCHAR(20) NOT NULL DEFAULT'' COMMENT'职位',
	`add_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'入职时间'
)CHARSET utf8 COMMENT'员工记录表';

INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('z3',22,'manager',NOW());
INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('July',23,'dev',NOW());
INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('2000',23,'dev',NOW());

建立索引ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(name,age,pos);

索引的順序位元name-age-pos

顯示其索引有沒有show index from staffs;

Mysql索引最左前綴的原則是什麼

##透過顛倒其左右順序,其執行都是一樣的

主要的語句是這三句

  1. explain select *from staffs where name='z3'and age=22 and pos='manager';

  2. explain select *from staffs where pos='manager' and name='z3 'and age=22;

  3. explain select *from staffs where age=22 and pos='manager' and name='z3';

Mysql索引最左前綴的原則是什麼

以上三者的順序顛倒,都使用到了聯合索引

最主要是因為MySQL中有查詢最佳化器explain,所以sql語句中欄位的順序不需要跟聯合索引定義的欄位順序相同,查詢最佳化器會判斷修正這條SQL語句以什麼樣的順序執行效率高,最後才能產生真正的執行計畫

#不論以何種順序都可使用到聯合索引

3. 部分索引順序

3.1 正序

#如果是按照順序(缺胳膊斷腿的),都是一樣的

  1. explain select *from staffs where name=‘z3’;

  2. explain select *from staffs where name='z3’and age=22;

  3. explain select *from staffs where name='z3’and age=22;

Mysql索引最左前綴的原則是什麼

其type都是ref類型,但是其欄位長度會有微小變化,也就是它定義的字長長度變化而已

3.2 亂序

如果部分索引的順序打亂

  1. 只查第一個索引

    explain select *from staffs where name= 'z3';

  2. 跳過中間的索引

    explain select *from staffs where name='z3' and pos='manager';

  3. 只查最後的索引

    explain select *from staffs where pos='manager';

Mysql索引最左前綴的原則是什麼

可以發現正序的時候

如果缺手臂少腿,也是按照正常的索引

即使跳過了中間的索引,也是可以使用到索引去查詢

但是如果只查最後的索引

type就是all類型,直接整個表的查詢了(這是因為沒有從name一開始匹配,直接匹配pos的話,會顯示無序,)

有些時候type就是index類型,這是因為還是可以透過索引進行查詢

index是對所有索引樹進行掃描,而all是對整個磁碟的資料進行全表掃描

4. 模糊索引

類似模糊索引就會使用到like的語句

所以下面的三條語句

如果複合最左前綴的話,會使用到range或是index的類型進行索引

  1. explain select *from staffs where name like '3%'; 最左前綴索引,類型為index或者range

  2. explain select *from staffs where name like '%3%'; 類型為all,全表查詢

  3. #explain select *from staffs where name like '%3%';,類型為all,全表查詢

Mysql索引最左前綴的原則是什麼

5. 範圍索引

如果查詢多個欄位的時候,出現了中間是範圍的話,建議刪除該索引,剔除中間索引即可

具體思路如下

建立一张单表

CREATE TABLE IF NOT EXISTS article(
	id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
	author_id INT(10) UNSIGNED NOT NULL,
	category_id INT(10) UNSIGNED NOT NULL,
	views INT(10) UNSIGNED NOT NULL,
	comments INT(10) UNSIGNED NOT NULL,
	title VARCHAR(255) NOT NULL,
	content TEXT NOT NULL
);

INSERT INTO article(author_id,category_id,views,comments,title,content)
VALUES
(1,1,1,1,'1','1'),
(2,2,2,2,'2','2'),
(1,1,3,3,'3','3');

经过如下查询:

explain SELECT id, author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1;

Mysql索引最左前綴的原則是什麼

发现其上面的单表查询,不是索引的话,他是进行了全表查询,而且在extra还出现了Using filesort等问题

所以思路可以有建立其复合索引

具体建立复合索引有两种方式:

  1. create index idx_article_ccv on article(category_id,comments,views);

  2. ALTER TABLE 'article' ADD INDEX idx_article_ccv ( 'category_id , 'comments', 'views' );

Mysql索引最左前綴的原則是什麼

但这只是去除了它的范围,如果要去除Using filesort问题的话,还要将其中间的条件范围改为等于号才可满足

发现其思路不行,所以删除其索引 DROP INDEX idx_article_ccv ON article;

Mysql索引最左前綴的原則是什麼

主要的原因是:

这是因为按照BTree索引的工作原理,先排序category_id,如果遇到相同的category_id则再排序comments,如果遇到相同的comments 则再排序views。

当comments字段在联合索引里处于中间位置时,因comments > 1条件是一个范围值(所谓range),MySQL无法利用索引再对后面的views部分进行检索,即range类型查询字段后面的索引无效。

所以建立复合索引是对的

但是其思路要避开中间那个范围的索引进去

只加入另外两个索引即可create index idx_article_cv on article(category_id, views);

Mysql索引最左前綴的原則是什麼

以上是Mysql索引最左前綴的原則是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除