MySQL覆盖索引和性能测试

覆盖索引:如果一个索引包含全部需要查询的字段,就称之为“覆盖索引”

举例:

  • 索引(a,b)
  • 查询 SELECT a,b FROM table_1;
索引包含了a,b字段,这两个字段又正好是以上查询所需的字段,因此索引(a,b)对这个查询而言是覆盖索引

覆盖索引的优点

  • 索引条目通常远小于数据行大小,因此如果只需要读取索引,能够极大减少数据访问量
  • 某些引擎例如MyISAM在内存中只缓存索引,不缓存数据行,因此如果需要读取数据,则需要浪费一次系统调用,覆盖索引可以避免这次开销
  • (高性能MySQL原文)由于InnoDB的聚簇索引,覆盖索引对InnoDB表特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。

EXPLAIN分析

mysql> EXPLAIN SELECT uper_date,uper_category,date_type FROM uper_all_rank WHERE uper_date='20180625';
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
| id | select_type | table         | partitions | type | possible_keys                   | key                 | key_len | ref   | rows  | filtered | Extra       |
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
|  1 | SIMPLE      | uper_all_rank | NULL       | ref  | up_date_idx,test_covering_index | test_covering_index | 42      | const | 55942 |   100.00 | Using index |
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
  • 最后一列Extra写明Using index

性能简单对比

测试表uper_all_rank
表结构如下

mysql> DESC uper_all_rank;
+-------------------+---------------+------+-----+-------------------+----------------+
| Field             | Type          | Null | Key | Default           | Extra          |
+-------------------+---------------+------+-----+-------------------+----------------+
| id                | int(11)       | NO   | PRI | NULL              | auto_increment |
| date_type         | varchar(10)   | NO   | MUL | NULL              |                |
| uper_date         | varchar(10)   | NO   | MUL | NULL              |                |
| uper_source       | varchar(30)   | NO   |     | NULL              |                |
| uper_account      | varchar(200)  | NO   | MUL | NULL              |                |
| uper_uid          | varchar(200)  | NO   | MUL | NULL              |                |
| uper_name         | varchar(200)  | NO   |     | NULL              |                |
| all_source_indexs | longtext      | NO   |     | NULL              |                |
| youmi_index       | decimal(10,2) | NO   |     | NULL              |                |
| uper_rank         | int(11)       | NO   |     | NULL              |                |
| last_rank         | int(11)       | NO   |     | NULL              |                |
| uper_category     | varchar(50)   | NO   |     |                   |                |
| is_all_category   | int(11)       | NO   |     | 1                 |                |
| create_time       | datetime      | NO   |     | CURRENT_TIMESTAMP |                |
| uper_avatar       | varchar(512)  | NO   |     |                   |                |
+-------------------+---------------+------+-----+-------------------+----------------+
15 rows in set (0.00 sec)


mysql> SELECT count(*) FROM uper_all_rank;
+----------+
| count(*) |
+----------+
|   293196 |
+----------+
1 row in set (0.04 sec)

表索引如下

mysql> SHOW INDEX FROM uper_all_rank;
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table         | Non_unique | Key_name     | Seq_in_index | Column_name     | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| uper_all_rank |          0 | PRIMARY      |            1 | id              | A         |      265702 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          0 | date_type    |            1 | date_type       | A         |           1 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          0 | date_type    |            2 | uper_date       | A         |          17 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          0 | date_type    |            3 | uper_source     | A         |          17 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          0 | date_type    |            4 | uper_account    | A         |      265160 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          0 | date_type    |            5 | is_all_category | A         |      271397 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          1 | account_idx  |            1 | uper_account    | A         |       87004 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          1 | dtype_idx    |            1 | date_type       | A         |           1 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          1 | up_date_idx  |            1 | uper_date       | A         |          15 |     NULL | NULL   |      | BTREE      |         |               |
| uper_all_rank |          1 | uper_uid_idx |            1 | uper_uid        | A         |       87023 |     NULL | NULL   |      | BTREE      |         |               |
+---------------+------------+--------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.00 sec)

添加测试索引如下

mysql> CREATE INDEX test_covering_index ON uper_all_rank (uper_date, uper_category);
Query OK, 0 rows affected (0.53 sec)
Records: 0  Duplicates: 0  Warnings: 0

EXPLAIN如下

  • 非覆盖索引
mysql> explain SELECT uper_date,uper_category,date_type FROM uper_all_rank WHERE uper_date=20180625 AND uper_category='时尚';
+----+-------------+---------------+------------+------+---------------------------------+------+---------+------+--------+----------+-------------+
| id | select_type | table         | partitions | type | possible_keys                   | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+---------------+------------+------+---------------------------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | uper_all_rank | NULL       | ALL  | up_date_idx,test_covering_index | NULL | NULL    | NULL | 287641 |     1.00 | Using where |
+----+-------------+---------------+------------+------+---------------------------------+------+---------+------+--------+----------+-------------+
1 row in set, 5 warnings (0.00 sec)
  • 覆盖索引
mysql> explain SELECT uper_date,uper_category FROM uper_all_rank WHERE uper_date=20180625 AND uper_category='时尚';
+----+-------------+---------------+------------+-------+---------------------------------+---------------------+---------+------+--------+----------+--------------------------+
| id | select_type | table         | partitions | type  | possible_keys                   | key                 | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+---------------+------------+-------+---------------------------------+---------------------+---------+------+--------+----------+--------------------------+
|  1 | SIMPLE      | uper_all_rank | NULL       | index | up_date_idx,test_covering_index | test_covering_index | 244     | NULL | 287641 |     1.00 | Using where; Using index |
+----+-------------+---------------+------------+-------+---------------------------------+---------------------+---------+------+--------+----------+--------------------------+
1 row in set, 5 warnings (0.00 sec)
  • 查询结果
mysql> SELECT uper_date,uper_category FROM uper_all_rank WHERE uper_date=20180625 AND uper_category='时尚';
830 rows in set (0.06 sec)
SELECT uper_date,uper_category,date_type FROM uper_all_rank WHERE uper_date=20180625 AND uper_category='时尚';
830 rows in set (0.09 sec)

添加三列索引,查询条件其中两列,查询全3列字段

mysql> ALTER TABLE uper_all_rank DROP INDEX test_covering_index;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> CREATE INDEX test_covering_index ON uper_all_rank (uper_date, uper_category, date_type);
Query OK, 0 rows affected (0.59 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • 索引(uper_date, uper_category, date_type)
mysql> EXPLAIN SELECT uper_date,uper_category,date_type FROM uper_all_rank WHERE uper_date='20180625';
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
| id | select_type | table         | partitions | type | possible_keys                   | key                 | key_len | ref   | rows  | filtered | Extra       |
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
|  1 | SIMPLE      | uper_all_rank | NULL       | ref  | up_date_idx,test_covering_index | test_covering_index | 42      | const | 55942 |   100.00 | Using index |
+----+-------------+---------------+------------+------+---------------------------------+---------------------+---------+-------+-------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

26320 rows in set (0.04 sec)
  • 索引(uper_date, uper_category)
mysql> EXPLAIN SELECT uper_date,uper_category,date_type FROM uper_all_rank WHERE uper_date='20180625';
+----+-------------+---------------+------------+------+---------------------------------+-------------+---------+-------+-------+----------+-------+
| id | select_type | table         | partitions | type | possible_keys                   | key         | key_len | ref   | rows  | filtered | Extra |
+----+-------------+---------------+------------+------+---------------------------------+-------------+---------+-------+-------+----------+-------+
|  1 | SIMPLE      | uper_all_rank | NULL       | ref  | up_date_idx,test_covering_index | up_date_idx | 42      | const | 50808 |   100.00 | NULL  |
+----+-------------+---------------+------------+------+---------------------------------+-------------+---------+-------+-------+----------+-------+
1 row in set, 1 warning (0.00 sec)

26320 rows in set (0.05 sec)

总结

不确定数据量更大的时候是否会差异更明显

猜你喜欢

转载自blog.csdn.net/BDuck2014/article/details/80977033