最近在改数据库 Index 的一些事情
#Table devices, :client_type, :status are strings
add_index :devices, [:client_type]
add_index :devices, [:status, :client_type], length
这个表中还有其他好几个索引,个人觉得既有 :client_type
又有 :status, :client_type
联合索引有点多余。
如果我做个调整,将第二个索引顺序变成:client_type, :status
,那根据 MySQL 的最左原则,只查找:client_type
也能被 hit 到。
那就可以去掉单一的在:client_type
上做的索引了。顺便做了个测试。
移掉:client_type
索引之前
mysql> explain select * from devices where client_type = 'IOSDevice';
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
| 1 | SIMPLE | devices | ref | index_devices_on_client_type | index_devices_on_client_type | 258 | const | 5145 | Using index condition |
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
1 row in set (0.00 sec)
mysql> select * from devices where client_type = 'BlackBerryDevice';
553 rows in set (0.03 sec)
移掉两个索引并建立:client_type, :status
之后
mysql> explain select * from devices where client_type = 'IOSDevice';
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
| 1 | SIMPLE | devices | ref | index_client_type_and_status | index_client_type_and_status | 258 | const | 9711 | Using index condition |
+----+-------------+---------+------+------------------------------+------------------------------+---------+-------+------+-----------------------+
1 row in set (0.00 sec)
mysql> select * from devices where client_type = 'BlackBerryDevice';
553 rows in set (0.01 sec)
前后结果对比让我很惊讶。联合索引结果比单索引还快。
我的测试是在同一个数据库运行的,会不会是 MySQL 有对结果缓存,还是我测试的数据集太小?
另外像我这种应用场景,是否合适把单索引直接去掉?假设查询:client_type
和 :client_type, :status
需求差不多。