如何优化这个MySQL慢(非常慢)的查询?

问题描述:

我有一个2GB的MySQL表,500k行,我在没有负载的系统上运行以下查询。如何优化这个MySQL慢(非常慢)的查询?

select * from mytable 
where name in ('n1', 'n2', 'n3', 'n4', ... bunch more...) 
order by salary 

它需要一个文件夹,并在50到70秒之间完成。

当按工资排序并在应用程序中进行排序时,总运行时间(包括排序)将减少到大约25-30秒。但这还是太多了。

任何想法如何加快这一点?

谢谢。

+0

请参阅:http://*.com/questions/1204402/how-do-i-ask-for-help-optimizing-fixing-queries-in-mysql – hobodave 2009-08-04 03:58:09

将名称列表放入临时表中,然后在两个表上进行内部连接。这种方式比梳理每一行的整个列表要快得多。这是伪代码:

create temporary table names 
    (name varchar(255)); 

insert into names values ('n1'),('n2'),...,('nn'); 

select 
    a.* 
from 
    mytable a 
    inner join names b on 
     a.name = b.name 

另外请注意,name应该有一个索引。这让事情变得更快很多。感谢托马斯做这个笔记。

+3

确保原始表的名称上有索引充分利用连接。 – 2009-08-02 23:25:03

+0

谢谢,这有点快;对于相同的查询大约25s,但25s仍然不是真正的改进... – CharlesS 2009-08-02 23:37:21

create index xyz on mytable(name(6)); 

“IN”查询是几乎送花儿给人低效的,因为它们是概念性地处理这样的:

select * from mytable where name = n1 
or name = n2 
or name = n3 
... 

我上面给出可以意味着查询优化的索引通过索引来访问行而不是表扫描。

一些想法:

  • 你必须选择*,您可以只选择一个子集脱身?
  • 如果你能逃脱选择一个子集,你可以添加一个覆盖指数,已经由工资排序
  • 如果一切具有相同的模式,你可以不喜欢(“N%”)

尝试使用子查询选择想要的行,然后对该子查询的结果进行排序。 See this question

而且你的name的索引mytable对吧?

根据数据分布和您的WHERE子句匹配的行量,你可能想尝试(工资,名)索引甚至(姓名,工资)尽管后者很可能将不对于这类查询非常有用。

您可能还想增加sort_buffer_size设置。单独测试一切,并比较EXPLAIN的输出。