好好学习,天天向上;知道 MYSQL 联合索引概念,但实际应用起来却一头雾水。
感谢,面试我的朋友,给我指点。
本文按 https://www.jianshu.com/p/499cf5795de5 复刻而来,MYSQL 版本为 5.6.17-log。
0、前期准备
本地 MYSQL版本为 5.6.17-log。
mysql创建一张表,表名:yjl_test_index
id列为 主键,int类型 ,自增
a,b,c,d,e 全部是int(11)
为(a,b,c)添加一个联合索引 index_abc,索引方法为 BTREE
CREATE TABLE `yjl_test_index` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `a` int(11) unsigned DEFAULT '0', `b` int(11) unsigned DEFAULT '0', `c` int(11) unsigned DEFAULT '0', `d` int(11) unsigned DEFAULT '0', `e` int(11) unsigned DEFAULT '0', PRIMARY KEY (`id`), KEY `index_abc` (`a`,`b`,`c`) USING BTREE ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
1、写入测试数据
以下为 TP3.2 代码:
$model = M('test_index'); $ins = []; $max = 100*10000; // 100 万条记录 for ($i = 1; $i<1000000; $i++) { $data = [ 'a' => mt_rand(0, 1000), 'b' => mt_rand(0, 10000), 'c' => mt_rand(0, 100000), 'd' => mt_rand(0, 1000), 'e' => mt_rand(0, 1000), ]; $ins[] = $data; if ($i % 10000 == 0) { $model->addAll($ins); $ins = []; } } if (!empty($ins)) $model->addAll($ins);
2、索引测试
AND AND 只要用到了最左侧a列,和顺序无关 都会使用 索引
#使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 AND b = 2 AND c = 3; #使用索引 EXPLAIN SELECT * from yjl_test_index where c = 1 AND b = 2 AND a = 3; #使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 AND b = 2; #使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 AND c = 3; #使用索引 EXPLAIN SELECT * from yjl_test_index where c = 1 AND a = 2;
不包含最左侧的 a 的不使用索引
# 未使用索引 EXPLAIN SELECT * from yjl_test_index where c = 3; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where b = 2; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where b = 2 AND c = 3; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where c = 1 AND b = 2;
OR 不使用索引
# 未使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 AND b = 2 OR c = 3; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 OR b = 2 AND c = 3; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where a = 1 OR b = 2 OR c = 3;
最左侧的‘a’列 被大于,小于,不等于比较的 ,不使用索引
# 未使用索引 EXPLAIN SELECT * from yjl_test_index where a > 1 AND b = 2 AND c = 3; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where a > 1; # 未使用索引 EXPLAIN SELECT * from yjl_test_index where a <> 1 AND b = 2 AND c = 3;
特殊情况,因为 最左原则的 a 字段,库中最大值为 1000,小于 155 时,也走索引
# 使用索引 EXPLAIN SELECT * from yjl_test_index where a < 155 AND b=2 AND c=3; # 不使用索引 EXPLAIN SELECT * from yjl_test_index where a < 200 AND b=2 AND c=3; # 不使用索引 EXPLAIN SELECT * from yjl_test_index where a > 155;
引自:
mysql 联合索引 复合索引(abc)如何索引命中规则实测
相关:
覆盖索引、联合索引、索引下推
MySQL之 索引下推
【mysql】索引 回表 覆盖索引 索引下推
mysql-覆盖索引
mysql高效索引之覆盖索引
通俗易懂 索引、单列索引、复合索引、主键、唯一索引、聚簇索引、非聚簇索引、唯一聚簇索引 的区别与联系