0

我有一张这样的桌子

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_ids、600 个molecules_ids 和3500 个具有随机双值的Ts 的许多组合(约20 亿行)。

我的印象是,对于像这样的查询

SELECT T, value FROM values WHERE molecule_id = X AND descriptor_id = Y

mysql 将使用两个键,然后与结果相交。但是Explain extended在这个查询上做一个告诉我它只使用了 index2,在 index1 和 index2 之间进行了选择。

分子 ID = X 命中大约 1/600 的表格。descriptor_id = Y 命中表的一小部分(如 0.001%)或大约 1/700,具体取决于 Y。

看起来相交会比仅使用 index2 并扫描超过 250 万行的其余部分更快。即使 3000 个descriptor_id 分布均匀,它仍然会平均留下 800,000 行要扫描。

我错过了什么?

4

2 回答 2

0

我相信index_merge只有在至少一个键上进行范围扫描时才会使用操作。您的示例查询只有相等谓词,MySQL 没有将其视为范围扫描。

于 2012-07-12T16:25:28.580 回答
0

spencer7593 说得对。index_merge 仅在范围情况下发生。如果你AND是一个OR它会触发一个 index_merge。但是,既然是AND,为什么不在molecule_id和上建立一个多列索引descriptor_id呢?这会给你带来更好的结果,更快。如果descriptor_id更独特(如您所述),请执行以下操作:

ALTER TABLE values ADD INDEX descriptor_molecule (descriptor_id, molecule_id, T, value)

只要您的查询在 where 子句中的两列都带有AND条件,它就会使用该索引。在这种情况下,我实际上会删除你的index2,因为如果查询只有descriptor_idwhere 子句中的列,它仍然可以使用descriptor_molecule索引作为前缀索引。另外,索引所有 4 列将为您提到的查询创建一个覆盖索引,从而大大加快您的查询速度。

于 2012-07-12T16:40:38.643 回答