我遇到了一个我有桌子的问题,描述如下:
mysql> desc myTable;
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| score | int(11) | YES | MUL | 0 | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| previous_score | int(11) | NO | MUL | 0 | |
+---------------------+--------------+------+-----+---------+----------------+
使用以下索引:
mysql> show indexes from myTable;
+-------+------------+-------------------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| myTable | 0 | PRIMARY | 1 | id | A | 48 | NULL | NULL | | BTREE | | |
| myTable | 1 | index_my_table_on_previous_score | 1 | previous_score | A | 48 | NULL | NULL | | BTREE | | |
| myTable | 1 | index_my_table_on_score | 1 | score | A | 48 | NULL | NULL | YES | BTREE | | |
+-------+------------+-------------------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
问题如下:
mysql> select count(*) from myTable where score > 10;
+----------+
| count(*) |
+----------+
| 48 |
+----------+
1 row in set (0.07 sec)
mysql> select count(*) from myTable ignore index(index_my_table_on_score) where score > 10;
+----------+
| count(*) |
+----------+
| 48 |
+----------+
1 row in set (0.00 sec)
如您所见,使用索引会产生较慢结果,而不是执行全表扫描。由于我在列previous_score
上有另一个索引,因此我决定使用explain
来进一步了解该问题:
mysql> select count(*) from myTable where previous_score > 10;
+----------+
| count(*) |
+----------+
| 48 |
+----------+
1 row in set (0.00 sec)
所以,正如你所看到的那样,美好而快速。我们来做explain
比较:
mysql> explain select count(*) from myTable where score > 10;
+----+-------------+-------+-------+----------------------+----------------------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+----------------------+----------------------+---------+------+------+--------------------------+
| 1 | SIMPLE | myTable | range | index_my_table_on_score | index_my_table_on_score | 5 | NULL | 24 | Using where; Using index |
+----+-------------+-------+-------+----------------------+----------------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select count(*) from myTable where previous_score > 10;
+----+-------------+-------+-------+-------------------------------+-------------------------------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------------------+-------------------------------+---------+------+------+--------------------------+
| 1 | SIMPLE | myTable | index | index_my_table_on_previous_score | index_my_table_on_previous_score | 4 | NULL | 48 | Using where; Using index |
+----+-------------+-------+-------+-------------------------------+-------------------------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
作为附加信息,我正在执行的查询将遍历我的表(48)中的所有结果。
score
进行范围扫描,并为previous_score
进行完整索引扫描吗 range scan
慢于full index
扫描?范围扫描应该比索引扫描更好,索引扫描比全表扫描更好。对于我的特定用例,显然不是这种情况。 非常感谢任何解释或建议。
答案 0 :(得分:1)
对于像这样的小表,这里有一种比计时更好的方法:
FLUSH STATUS;
SELECT SQL_NO_CACHE ...;
SHOW SESSION STATUS LIKE 'Handler%';
总结数字列是将SELECT
的一个变体与另一个变体进行比较的非常好的指标。
两个EXPLAINs
都说他们是Using index
- 实际上在形成索引的BTree中执行查询。没有表扫描。
请提供SHOW CREATE TABLE
,它比DESCRIBE
更具描述性。
如果'缓存'很冷,这可以解释0.07 sec
。