【问题标题】:MySQL optimize subqueriesMySQL优化子查询
【发布时间】:2011-10-02 09:45:58
【问题描述】:

我想优化这个查询(因为子查询通常不快),但我迷路了,因为我无法使用对性能更好的连接来重写它,你能帮我解决这个问题吗?

SELECT id, company, street, number, number_addition, postalcode, telephone
FROM clients
    WHERE (postalcode BETWEEN '1000' AND '9000') AND street = (
        SELECT DISTINCT street FROM clients WHERE (postalcode BETWEEN '1000' AND '9000') AND postalcode <= (
            SELECT MIN(postalcode) FROM clients WHERE street = 'Main Street' AND     (postalcode BETWEEN '1000' AND '9000'))
        ORDER BY postalcode DESC LIMIT 1, 1)
ORDER BY postalcode DESC, street DESC, number DESC, number_addition DESC, telephone DESC
LIMIT 1

感谢你们的时间。

【问题讨论】:

  • 这个查询真的很慢吗?不要随意优化。在您的 MySQL 服务器中启用 slow_query_log。这将在您的 slow_query_log_file 中记录花费超过 long_query_time 的查询。

标签: mysql performance join subquery


【解决方案1】:

SELECT DISTINCT street ORDER BY postalcode 没有意义(而且我认为不是有效的 ANSI SQL),除非postalcode 在功能上依赖于street——我认为它不是,因为你的 get-lowest -postalcode-on-Main-Street 内部子选择如果是就没有意义。 MySQL 会让你侥幸逃脱,但结果会不一致。你想在这里说什么?

我认为这应该不会特别慢,因为您拥有的不是依赖子查询;子查询只执行一次,并且不会对每个外部行重复执行。您可以将其重写为三个单独的查询——

  1. 获取 Main Street 上最低的邮政编码;
  2. 获取第二高邮政编码低于 (1) 的街道(不一致);
  3. 获取街道上客户的详细信息 (2)。

在执行上没有区别。 (实际上,为了清楚起见,这样做可能会更好。)

可以将这些重写为连接,使用 self-left-joins-on-less-than-is-null 来获得最小值/最大值,但我认为你不会获得对于这个例子来说,任何东西都会变得非常混乱,因为它有两个级别的加入和第二高的要求。这个查询在实践中是不是特别慢? EXPLAIN 是什么样的?您是否为postalcodestreet 编制了索引?

【讨论】:

  • SELECT DISTINCT street ORDER BY postalcode - 问题是我有一张客户表,我想获得这张表中的所有街道。每条街道都可以有多个邮政编码,所以我想选择邮政编码的最低值并以此为街道排序。
  • 我还不能在生产环境中测试这个,但是因为这是一个在应用程序前端运行的查询(很少)我认为加快这个速度是个好主意,但是如果你认为这还不错,我会等待它在生产中的运行方式。顺便说一句,邮政编码和街道都被编入索引。感谢您的宝贵时间。
  • 您不是按照最小邮政编码对街道进行排序,而是按照每条街道的一个随机邮政编码进行排序。其他数据库会将其标记为错误,因为这通常是一个错误。试试SELECT street ... GROUP BY street ORDER BY MIN(postcode)
猜你喜欢
  • 2011-11-27
  • 2021-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多