最近在改数据库 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需求差不多。