MySql需要很长时间来优化无连接查询

时间:2010-01-28 10:33:27

标签: sql mysql optimization join query-optimization

我们有一个简单的查询,如下所示:

SELECT a,b,c,d FROM table WHERE a=1 and b IN ('aaa', 'bbb', 'ccc', ...)

IN子句中没有任何连接,5000个辅助值。

现在,此查询需要1-20秒才能在非常强大的(16核心)服务器上运行。该表在(a,b)上有一个索引,我们也尝试将索引反转为(b,a)。服务器有大量的内存,没有人写这个表 - 只有5个进程运行选择,如上所述。

我们做了一些分析,发现有些查询在“JOIN :: optimize”(。\ sql_select.cc 977)中花了3.5秒。我提醒你,查询根本不使用连接。

在无连接表上优化连接所花费的大量时间可能是什么原因?

以下是EXPLAIN SELECT的结果:

id select_type table type   possible_keys key    key_len ref rows   Extra
1  SIMPLE     table range    IX_A_B       IX_A_B 65      \N  5000   Using where

6 个答案:

答案 0 :(得分:5)

尝试将5000个值放在临时表中:

declare @t table (b varchar(10))
insert into b select 'aaa'
union all select 'bbb'
union all select 'c'
....

select table.*
from table
join @t t on table.b = t.b
where table.a = 1

答案 1 :(得分:2)

b IN(x,y,...)被翻译成:(b = x OR b = y OR b = ...)

这意味着你要对表中的每个值进行5000次if-check。

答案 2 :(得分:1)

您是否在字段a上有索引,尤其是b?

如果您在优化SQL中寻求帮助,则应附加

EXPLAIN SELECT a,b,c,d FROM table WHERE a=1 and b IN ('aaa', 'bbb', 'ccc', ...)

同样,没有它,人们只能猜测。

答案 3 :(得分:1)

使用像这样的IN子句也可以是一个连接,所以它不是完全无连接的。

你在(a,b)上有一个索引是相当不错的,但是你必须想知道它是如何得到值c和d ...最后,它可能会忽略索引和只是扫描整个桌子。

尝试在(a,b, c,d )上创建索引,以便索引包含您需要的所有数据。在SQL Server中,您可以使用包含的列来执行此操作,但我认为在mysql中您还需要包含其他列。这应该意味着您的查询可以直接进入a = 1记录,并开始查找与列表匹配的b的记录,然后它具有所需的所有信息。

答案 4 :(得分:0)

您的回答是考虑以下两个答案中的建议:
MySql takes a long time optimizing a join-less query
MySql takes a long time optimizing a join-less query

另外,你提到b是高度选择性的;这样:

我建议您将索引中列的顺序更改为(b,a)。如果优化器可以更快地缩小结果范围,那么使用索引就会更加敏锐。 (将最具选择性的列放在索引的前面通常是一个很好的经验法则;如果你想要偏离这个原则那么很少。)

答案 5 :(得分:-1)

Our DBA发现这是reported bug