美文网首页
联合索引命中测试

联合索引命中测试

作者: 大猪小猪在菜盘 | 来源:发表于2019-01-30 13:46 被阅读0次

总的来讲就是最左前缀原理,但是这个具体的原理比较抽象,我们来做测试理解这个原理。

创建一张表,我们建立一个联合索引

CREATE TABLE IF NOT EXISTS `cheatcode` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `game` VARCHAR(45) NOT NULL DEFAULT '',
  `feature` VARCHAR(45) NOT NULL DEFAULT '',
  `password` VARCHAR(45) NOT NULL DEFAULT '',
  `comment` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  INDEX `CINDEX` (`game` ASC, `feature` ASC, `password` ASC))
ENGINE = InnoDB;
INSERT INTO `cheatcode`(`game`,`feature`,`password`)VALUES('warcraft','money','greedisgood');
INSERT INTO `cheatcode`(`game`,`feature`,`password`)VALUES('warcraft','showmap','iseedeadpeople');
INSERT INTO `cheatcode`(`game`,`feature`,`password`)VALUES('warcraft','invincible','whosyourdaddy');
INSERT INTO `cheatcode`(`game`,`feature`,`password`)VALUES('starcraft','showmap','blacksheepwall');
INSERT INTO `cheatcode`(`game`,`feature`,`password`)VALUES('starcraft','speed','operationcwal');

为了使所有的查询能走索引而不被优化器优化,我们再插入1000万条随机数据。

1. 精确匹配

索引查询条件顺序排列:

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `game`='warcraft' AND `feature`='money' AND `password`='greedisgood';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref               | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | cheatcode | NULL       | ref  | CINDEX        | CINDEX | 546     | const,const,const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

索引查询条件无序排列:

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `feature`='money' AND `game`='warcraft' AND `password`='greedisgood';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref               | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | cheatcode | NULL       | ref  | CINDEX        | CINDEX | 546     | const,const,const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

无任何影响,执行器在执行之前会优化。

2. 部分匹配

我们一共做以下几种测试:

1. 只命中game, feature, password其中之一
mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref   | rows    | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-------+
|  1 | SIMPLE      | cheatcode | NULL       | ref  | CINDEX        | CINDEX | 182     | const | 1230430 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `feature`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | cheatcode | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10641430 |    10.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `password`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | cheatcode | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10641430 |    10.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

这个测试至少说明联合索引只对排在第一位的game生效了,feature和password并没有生效,我们再做个总数查询耗时来验证一下:

mysql> SELECT COUNT(0) FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (0.64 sec)

mysql> SELECT COUNT(0) FROM `cheatcode` WHERE `feature`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (3.36 sec)

mysql> SELECT COUNT(0) FROM `cheatcode` WHERE `password`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (3.57 sec)

验证结果符合。

2. 命中任意两个
mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt' AND `feature`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+---------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref         | rows    | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+---------+----------+-------+
|  1 | SIMPLE      | cheatcode | NULL       | ref  | CINDEX        | CINDEX | 364     | const,const | 1230430 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------------+---------+----------+-------+
1 row in set, 1 warning (0.01 sec)

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt' AND `password`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-----------------------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref   | rows    | filtered | Extra                 |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-----------------------+
|  1 | SIMPLE      | cheatcode | NULL       | ref  | CINDEX        | CINDEX | 182     | const | 1230430 |    10.00 | Using index condition |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+---------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM `cheatcode` WHERE `feature`='TRjJiqdNoPtwcJcmHBwt' AND `password`='TRjJiqdNoPtwcJcmHBwt';
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | cheatcode | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10641430 |    10.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

结果略有不同,从结果上来看,game+feature是最好的组合,两个字段全部命中了,而game+password则只命中了game,feature+password则一个也没命中,我们再做一下总数查询验证:

mysql>  SELECT COUNT(0) FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt' AND `feature`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (0.97 sec)

mysql> SELECT COUNT(0) FROM `cheatcode` WHERE `game`='TRjJiqdNoPtwcJcmHBwt' AND `password`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (1.02 sec)

mysql>  SELECT COUNT(0) FROM `cheatcode` WHERE `feature`='TRjJiqdNoPtwcJcmHBwt' AND `password`='TRjJiqdNoPtwcJcmHBwt';
+----------+
| COUNT(0) |
+----------+
|   666747 |
+----------+
1 row in set (4.11 sec)

结果符合查询条件的索引命中情况,第一种组合,因为命中最多,所以性能最好。第二种次之,第三种没命中,就是走全表扫描统计。

相关文章

  • 联合索引命中测试

    总的来讲就是最左前缀原理,但是这个具体的原理比较抽象,我们来做测试理解这个原理。 创建一张表,我们建立一个联合索引...

  • MySQL联合索引和索引不生效的情况研究

    联合索引 测试前准备 mysql版本5.7.22 创建表结构: 插入临时数据: 表内容: 创建联合索引: 测试联合...

  • PHP题目分享与答案(2)

    2:索引分为哪些?如何创建索引?索引如何优化?A,B,C联合索引如何才能命中索引? MySQL索引分为主键索引,唯...

  • 数据库

    1.select * from table where a>0 and b<0,ab是联合索引,问索引能不能命中?...

  • MySQL索引的尝试

    关于MySQL索引的命中问题,做了一点测试。 首先,关于索引无法命中的问题,查了不少资料,大概是这么说的: - 在...

  • MySQL-联合索引

    一、什么是联合索引 两个或更多个列上的索引被称作联合索引,联合索引又叫复合索引。对于复合索引:Mysql从左到右的...

  • Mysql

    2020-01-21 联合索引本质 当创建(a,b,c)联合索引时,相当于创建了(a)单列索引,(a,b)联合索引...

  • 日常问题记录:更新数据库锁表(Lock wait timeout

    问题:并发更新sql出现锁表的情况 解决:添加索引分析:我这里是两个字段,考虑添加联合索引或者唯一索引测试:1、联...

  • mysql 联合索引 复合索引(abc)如何索引命中规则实测

    可以略过 最近找工作面试时,被问及了mysql联合索引的一些问题,之前看过‘高性能mysql’中第五章关于索引的部...

  • 索引的技术点

    联合索引:多字段组合索引,加速组合条件查询 联合索引要满足从左到右的查询需求,例如(a,b,c)的联合索引,能够加...

网友评论

      本文标题:联合索引命中测试

      本文链接:https://www.haomeiwen.com/subject/tdvqsqtx.html