之所以有這個最左前綴索引
歸根究底是mysql的資料庫結構B 樹
在實際問題中例如
索引index (a,b,c)有三個字段,
使用查詢語句select * from table where c = '1'
,sql語句不會走index索引的
select * from table where b =‘1’ and c ='2'
這個語句也不會走index索引
最左前綴匹配原則:在MySQL建立聯合索引時會遵守最左前綴匹配原則,即最左優先,在檢索資料時從聯合索引的最左邊開始匹配
為了更好辨別這種情況,透過建立表格以及索引的情況進行分析
建立一張表,建立一個聯合索引,如果順序顛倒,其實還是可以識別的,但是一定要有它的全部部分
建立表
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;
explain select *from staffs where name='z3'and age=22 and pos='manager';
explain select *from staffs where pos='manager' and name='z3 'and age=22;
explain select *from staffs where age=22 and pos='manager' and name='z3';
explain select *from staffs where name=‘z3’;
explain select *from staffs where name='z3’and age=22;
explain select *from staffs where name='z3’and age=22;
explain select *from staffs where name= 'z3';
explain select *from staffs where name='z3' and pos='manager';
explain select *from staffs where pos='manager';
explain select *from staffs where name like '3%'; 最左前綴索引,類型為index或者range
explain select *from staffs where name like '%3%'; 類型為all,全表查詢
#explain select *from staffs where name like '%3%';,類型為all,全表查詢
建立一张单表
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;
发现其上面的单表查询,不是索引的话,他是进行了全表查询,而且在extra还出现了Using filesort等问题
所以思路可以有建立其复合索引
具体建立复合索引有两种方式:
create index idx_article_ccv on article(category_id,comments,views);
ALTER TABLE 'article' ADD INDEX idx_article_ccv ( 'category_id , 'comments', 'views' );
但这只是去除了它的范围,如果要去除Using filesort问题的话,还要将其中间的条件范围改为等于号才可满足
发现其思路不行,所以删除其索引 DROP INDEX idx_article_ccv ON article;
主要的原因是:
这是因为按照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索引最左前綴的原則是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!