我有一张简单的表
stock_ledger_id INT(10) (Primary)
piece_to_bin_id INT(10)
quantity INT(11)
create_datetime TIMESTAMP
... and a few VARCHARs
有一些简单的索引
Key_name Cardinality
PRIMARY 1510443
piece_to_bin_id 100696
这个相当简单的查询大约需要8秒钟:
SELECT piece_to_bin_id,
SUM(quantity),
MAX(create_datetime)
FROM stock_ledger
GROUP BY piece_to_bin_id
这是EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE stock_ledger ALL NULL NULL NULL NULL 1512976 Using temporary; Using filesort
通过强制索引,我发现我可以将其降低到约.5秒:
SELECT piece_to_bin_id,
SUM(quantity),
MAX(create_datetime)
FROM stock_ledger
FORCE INDEX (piece_to_bin_id)
GROUP BY piece_to_bin_id
然后EXPLAIN看起来像这样:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE stock_ledger index NULL piece_to_bin_id 4 NULL 1512976
我使用的是MySQL 5.1.41,表格是MyISAM,之前我确实运行过ANALYZE TABLE。
所以我坚持“MySQL再次出错,只是强制索引”或者是否存在MySQL使用全表扫描的实际原因?也许我能解决一个问题?
答案 0 :(得分:1)
无论如何,查询需要一个完整的表扫描,可能是mysql试图避免从键值到行的额外转换。查询可能更多地受益于复合(piece_to_ bin_id,create_datetime)索引或甚至(piece_to_ bin_id,create_datetime,quantity)。后者将成为覆盖指数。
<强> UPD 强>
在您的情况下,似乎更快16倍的结果来自数据分布(可能是许多相邻的行具有相同的piece_to_bin_id
按create_datetime
排序)。 MyISAM似乎使用索引来减少结果行的数量,因为使用它们意味着随机磁盘I / O操作。
我从来没有引起任何关注,但我目前对10K行表的测试表明,MyISAM甚至没有使用索引来对查询进行排序,如:
SELECT indexed_field, another_field
FROM a_table
ORDER BY indexed_field;
即使indexed_field
是主键。