2 minutes
Week1025_share
ARTS - Share - 补12.24日
MySQL的联合索引
最左匹配原则
索引的重要性就不再说了,反正使用数据库的都知道,我们来说说联合索引。说到联合索引,就要说它的最左匹配原则,由于B+Tree 的特点,索引从左往右建,加入一张表 table(col1, col2, col3), 建立联合索引 create index idx_table_col1_col2 on table(col1, col2);
在查询时候 where col1 = xxx and col2 = xxx 和 where col1 ,都会用到这个联合索引,但是如果 where col2 = xxx , 这种情况是用不到联合索引的。
实际案例
本人在进行一个百万级表的查询时候,碰到了这个问题。
在使用 where create_date = xxxx时候, 使用执行计划查看:
+----+-------------+-------+------------+--------+-----------------------------+---------+---------+-------------------+---------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+-----------------------------+---------+---------+-------------------+---------+----------+----------------------------------------------+
| 1 | SIMPLE | d | <null> | ALL | idx_create_by | <null> | <null> | <null> | 2343409 | 1.23 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | c | <null> | eq_ref | PRIMARY | PRIMARY | 122 | d.apply_id | 1 | 100.0 | Using index |
| 1 | SIMPLE | u | <null> | eq_ref | PRIMARY | PRIMARY | 194 | d.create_by | 1 | 100.0 | Using where |
+----+-------------+-------+------------+--------+-----------------------------+---------+---------+-------------------+---------+----------+----------------------------------------------+
触发了全表扫描,而且,使用 show index from table; 查看索引情况:
+---------------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table | 0 | PRIMARY | 1 | id | A | 2342964 | <null> | <null> | | BTREE | | |
| table | 0 | table_unique | 1 | apply_id | A | 426585 | <null> | <null> | | BTREE | | |
| table | 0 | table_unique | 2 | create_date | A | 2296706 | <null> | <null> | | BTREE | | |
| table | 1 | table_groupId | 1 | group_id | A | 10 | <null> | <null> | YES | BTREE | | |
| table | 1 | table_time | 1 | pay_time | A | 409528 | <null> | <null> | YES | BTREE | | |
| table | 1 | table_time | 2 | create_date | A | 414810 | <null> | <null> | | BTREE | | |
| table | 1 | idx_create_by | 1 | create_by | A | 272 | <null> | <null> | | BTREE | | |
+---------------------+------------+-----------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
发现create_date 已经建立了索引,但是为什么查询计划里还是全表扫描呢?
最后使用 show create table table
; 来查看,算是看清楚了 该表使用了 (pay_time, create_date) 来作为联合索引,而 show index 里面显示的两个同名key_name ,其实就是联合索引的意思,怪我没有看仔细,漏了这个重要线索。
然后解决起来就是方便了,给create_date 建立单独的索引,然后查询时间从半分钟降到1秒以内。
总结
看题要仔细,不然很容易忽略细节,然后就容易南辕北辙,以为自己目前掌握的知识不足以解决,产生畏惧心理。
基础要打牢,最左匹配原则要结合实际案例来记忆,不然浮于表面,无法形成有效知识。
Read other posts