【问题标题】:How to optimize this MySQL slow (very slow) query?如何优化这个 MySQL 慢(非常慢)查询?
【发布时间】:2009-08-02 23:19:51
【问题描述】:

我有一个包含 500k 行的 2 gb mysql 表,我在没有负载的系统上运行以下查询。

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

文件排序需要 50 到 70 秒才能完成。

当按薪水删除订单并在应用程序中进行排序时,总运行时间(包括排序)减少到大约 25-30 秒。但这仍然太过分了。

知道如何加快速度吗?

谢谢。

【问题讨论】:

标签: mysql optimization


【解决方案1】:

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

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 上应该有一个索引。这让事情进展快得多。感谢 Thomas 做此笔记。

【讨论】:

  • 确保原始表在名称上有一个索引以充分利用联接。
  • 谢谢,这有点快;相同的查询大约需要 25 秒,但 25 秒仍然不是真正的改进......
  • 有或没有order by?使用 order by,查询速度提高了 50%,没有它只会稍微快一点。您将只需要在两个表上的名称上都有一个索引。然后在查询上运行 EXPLAIN 以查看它在做什么。
  • 您能否提供一些证明“IN”查询是错误选择的参考资料?根据我使用 Mysql (5.0+) 的经验,如果您使用连接、等号(一个名称 = 'xxx')或“IN”,则性能非常相似。我认为最重要的一点是正确的索引和服务器配置。
【解决方案2】:

一些想法:

  • 您是否需要选择 *,您可以只选择一个子集吗?
  • 如果您可以选择一个子集,您可以添加一个覆盖索引,该索引已经按薪水排序
  • 如果所有内容都具有相同的模式,您可以执行 LIKE('n%')

【讨论】:

    【解决方案3】:

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

    你在mytable 中确实有一个关于name 的索引,对吧?

    【讨论】:

      【解决方案4】:

      根据数据分布和您的 WHERE 子句匹配的行数,您可能希望尝试在 (salary, name) 甚至 (name, Salary) 尽管后者很可能对这类查询不是很有用。

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

      【讨论】:

        【解决方案5】:
        create index xyz on mytable(name(6));
        

        “IN”查询几乎总是低效的,因为它们在概念上是这样处理的:

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

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

        【讨论】:

        • 您能否提供一些证明“IN”查询几乎总是无效的参考资料?根据我对 Mysql (5.0+) 的经验,如果您使用连接或等号(一个名称 = 'xxx'),它们具有相同的性能。我认为最重要的一点是正确的索引和服务器配置。
        猜你喜欢
        • 1970-01-01
        • 2014-07-04
        • 1970-01-01
        • 1970-01-01
        • 2017-01-25
        • 2013-03-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-30
        相关资源
        最近更新 更多