InnoDB没有做索引合并

时间:2012-07-12 15:11:02

标签: mysql indexing innodb

我有一张这样的表

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行平均扫描。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

我相信只有在至少一个键上进行范围扫描时才会使用index_merge操作。您的示例查询只有等式谓词,MySQL看不到任何范围扫描。

答案 1 :(得分:0)

spencer7593没错。 index_merge仅在范围情况下发生。如果您的ANDOR,则会触发index_merge。但是,由于它是AND,为什么不在molecule_iddescriptor_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列将为您提到的查询创建覆盖索引,从而加快查询速度。