为什么这些MySQL查询在看起来相当的情况下需要如此不同的处理时间?

为什么这些MySQL查询在看起来相当的情况下需要如此不同的处理时间?,mysql,indexing,Mysql,Indexing,下面是三个MySQL查询。第一个在一个查询中返回我要查找的所有内容,而第二个在两个查询中返回相同的聚合结果 我想知道为什么单个查询的运行时间要长2-100秒,而三个查询之间的处理时间似乎应该相等。有没有办法优化单个查询,使其与单个查询一样快速运行?在单个查询的WHERE语句中添加更多的OR并不会增加处理时间,但在某些情况下,我需要执行更多的OR,最终单个查询的速度将与运行十个单独查询的速度一样快 单个查询似乎在运行后会被缓存,第一次运行可能需要几分钟,而单个查询总是在同一时间段内完成 多列索引在

下面是三个MySQL查询。第一个在一个查询中返回我要查找的所有内容,而第二个在两个查询中返回相同的聚合结果

我想知道为什么单个查询的运行时间要长2-100秒,而三个查询之间的处理时间似乎应该相等。有没有办法优化单个查询,使其与单个查询一样快速运行?在单个查询的WHERE语句中添加更多的OR并不会增加处理时间,但在某些情况下,我需要执行更多的OR,最终单个查询的速度将与运行十个单独查询的速度一样快

单个查询似乎在运行后会被缓存,第一次运行可能需要几分钟,而单个查询总是在同一时间段内完成

多列索引在这里会有很大的不同吗

值得注意的是,该表没有ID字段作为主索引。这是导致这种不受欢迎的行为的原因吗

在这里很难运行测试,因为表有一亿行,添加列和索引需要将近一天的时间

单一查询(4.2s)

等效聚合查询(每个查询0.8秒)

解释这些问题

id     select_type    table                     type    possible_keys              key          key_len  ref    rows     extra
1      SIMPLE         staging_company_search    range   name_word_0,name_word_1    name_word_0  102      NULL   2197605  Using index condition; Using where
1      SIMPLE         staging_company_search    ref     name_word_0,name_word_1    name_word_1  102      const  128      Using index condition; Using where
1      SIMPLE         staging_company_search    ref     name_word_0,name_word_1    name_word_0  102      const  33       Using index condition; Using where
数据库架构

CREATE TABLE `staging_company_search` (
  `name_id` int(11) unsigned NOT NULL DEFAULT '0',
  `name_word_0` varchar(100) NOT NULL,
  `name_word_1` varchar(100) NOT NULL,
  KEY `name_id` (`name_id`),
  KEY `name_word_0` (`name_word_0`),
  KEY `name_word_1` (`name_word_1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我认为这是因为MySQL处理索引时必须检查几个条件(“OR”)。这可以在“解释查询”中看到,第一个查询在返回结果之前需要检查更多的行

我相信两个小结果的结合应该会取得更好的效果。你能试试下面的吗

SELECT name_id
FROM staging_company_search
WHERE (name_word_0 = 'the' AND name_word_1 = 'glazier')
UNION ALL    
    SELECT name_id
    FROM staging_company_search
    WHERE (name_word_0 = 'bridgewaters' AND name_word_1 = '');

在第一个查询中使用OR子句会破坏索引的使用。MySQL那样有点傻。它正在做一个完整的表格扫描:查看每一行。您最好只使用联合在一起的查询


要使您的查询和仅查询更快,请在
(name\u word\u 0,name\u word\u 1,name\u id)
上创建一个复合索引。通过对该索引的随机访问可以完全满足您的查询,并且应该在2兆行表中运行亚秒。

这是因为mysql对简单查询只使用一个索引

如果在多个索引之间有选择,MySQL通常使用 查找最小行数(选择性最高)的索引 索引)

然而,mysql可以并且将使用两个索引,从版本5.0到。不幸的是,这种情况并不总是发生,即使发生了,也会产生结果

第一个explain输出显示索引合并优化没有在查询中与OR子句一起使用。它只使用
name\u word\u 0上的索引

name_word_0非常适合
,其中name_word_0='the'和name_word_1='glazier'但正如第三个解释的输出所示,它根本不适合
中的name\u word\u 0='bridgewaters'和name\u word\u 1=''

因此,组合查询的速度非常慢。您可以通过创建一个跨越name_word_0和name_word_1的复合索引来克服这一问题。我注意到你的钥匙很长。您可以创建一个部分索引,并可能进一步加快速度

CREATE INDEX word01 ON staging_company_search (name_word_0(20), name_word_1(20))

如果在第一个查询中尝试(‘the’、‘glazier’、(‘bridgewaters’、“”))中的(name_word_0、name_word_1)位置,会发生什么?甚至更慢。该查询还包含稍微不同的逻辑,结果是四个name_单词的组合,而不是两个。我明白了。两个等价的聚合查询的并集如何?解释计划是否显示了这两者之间的差异?我添加了解释结果。它们非常不同,但我不确定如何解释原因,或者如何调整以进行补偿。您可以尝试在单个查询中使用下面的where代码,看看它是否比我更快,然后我可以在您的表模式中回答y更快,其中(name_id>0和name_word_0='the'和name_word_1='glazier'),或者(name_id>0 name_word_0='bridgewaters'和name_word_1='');
SELECT name_id
FROM staging_company_search
WHERE (name_word_0 = 'the' AND name_word_1 = 'glazier')
UNION ALL    
    SELECT name_id
    FROM staging_company_search
    WHERE (name_word_0 = 'bridgewaters' AND name_word_1 = '');
CREATE INDEX word01 ON staging_company_search (name_word_0(20), name_word_1(20))