我有一张这样的表
CREATE TABLE values (
id int(10) auto_increment NOT NULL,
molecule_id int(5) NOT NULL,
descriptor_id int(5) NOT NULL,
T double DEFAULT NULL,
value double NOT NULL,
PRIMARY KEY (id),
KEY index1 (molecule_id, T),
KEY index2 (descriptor_id, T)
) ENGINE=InnoDB;
该表的行是3000个descriptor_id,600个分子_和3500个Ts的许多组合,具有随机双值(约20亿行)。
我认为对于像
这样的查询SELECT T, value FROM values WHERE molecule_id = X AND descriptor_id = Y
mysql将使用两个键然后交叉结果。但是对此查询执行Explain extended
告诉我它只使用index2,在index1和index2之间选择。
molecular_id = X约占表的1/600。 descriptor_id = Y命中表格的一小部分(如0.001%)或约1/700,具体取决于Y.
似乎交叉比仅使用index2并扫描超过250万行的其余部分更快。即使3000个descriptor_ids均匀分布,它仍然会留下800,000行平均扫描。
我错过了什么?
答案 0 :(得分:0)
我相信只有在至少一个键上进行范围扫描时才会使用index_merge
操作。您的示例查询只有等式谓词,MySQL看不到任何范围扫描。
答案 1 :(得分:0)
spencer7593没错。 index_merge仅在范围情况下发生。如果您的AND
为OR
,则会触发index_merge。但是,由于它是AND
,为什么不在molecule_id
和descriptor_id
上创建multi_column索引?这将为您带来更好的结果,并且更快。如果descriptor_id
更独特(如您所述),请执行以下操作:
ALTER TABLE values ADD INDEX descriptor_molecule (descriptor_id, molecule_id, T, value)
只要您的查询在where子句中具有AND
条件的两列,它就会使用此索引。在这种情况下,我实际上会删除index2
,因为如果查询在where子句中只有descriptor_id
列,它仍然可以使用descriptor_molecule
索引作为前缀索引。另外,索引所有4列将为您提到的查询创建覆盖索引,从而加快查询速度。