Mysql InnoDB未进行索引合并
我有一张这样的桌子Mysql InnoDB未进行索引合并,mysql,indexing,innodb,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),
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个描述符ID、600个分子ID和3500个随机双倍值(约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个描述符ID均匀分布,平均仍会有800000行需要扫描
我缺少什么?我相信只有在至少一个键上进行范围扫描时才会使用
索引\u合并
操作。您的示例查询只有相等谓词,MySQL没有将其视为范围扫描。spencer7593正确。索引合并仅在范围情况下发生。如果您的和
是或
,则会触发索引合并。然而,既然它是一个和,为什么不在分子id和描述符id上建立一个多列索引呢?这将使您更快地获得更好的结果。如果descriptor\u id
更具排他性(如您所述),请执行以下操作:
ALTER TABLE value添加索引描述符\u molecular(描述符\u id,molecular\u id,T,value)
只要您的查询在where子句中同时具有和
条件,它就会使用此索引。在这种情况下,我实际上会删除您的index2
,因为如果查询在where子句中只有descriptor\u id
列,它仍然可以使用descriptor\u
索引作为前缀索引。另外,索引所有4列将为您提到的查询创建一个覆盖索引,从而大大加快查询速度。覆盖索引可能会提供更好的性能(描述符id、分子id、T、值)
。(我打算建议一个索引(就像你那样)在你的回答中,我没有说到这里,只是回答了一个问题,为什么我们不希望MySQL执行索引合并
操作。问题是,描述符id、分子id、T的每一个组合在查询中都是可能的,即使有范围。像SELECT*这样的查询来自描述符id=X和分子I的值Y和Z之间的d仍然不合并,不能使用类似(分子id、描述符id)的索引。因此,如果我想以最佳性能涵盖所有可能性,我需要6个索引,不是吗?还有,有人能给我解释一下这篇博客文章吗?在我看来,它在第三个列表中的两个单列索引相交,就像我在问题中发布的一样。没关系,我在手册中发现了这个条件,我必须当WHERE子句被转换为不同键上的多个范围条件并与AND组合时,可以使用这种访问算法,每个条件都是以下条件之一:在这种形式中,索引正好有N个部分(也就是说,所有索引部分都被覆盖):key\u part1=const1和key\u part2=const2…和key\u partN=constN“。如果我有两个单独的单列索引,它确实会相交,但因为在我的表中,索引是多列的,所以不能使用它们相交。将t,value
添加到descriptor\id,molecular\u id
的索引中会很好。当我写我的响应时,我不在其中,试图弄清楚t是什么
是(我没有看到t
)列。不过,我的答案是肯定的。正如您所提到的,如果引入范围查找,它显然将停止在该列使用索引。在某些情况下,您将需要基于查询的多个索引。