【问题标题】:Optimise SQL query for the report优化报表的 SQL 查询
【发布时间】:2011-10-15 03:20:12
【问题描述】:

这是我编写的 SQL 查询,它运行良好但速度很慢。

SELECT D.Username, 
        SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes, 
        SUM(CASE WHEN D.type = 'No' THEN 1 ELSE 0 END) as No, 
        SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other, 
        SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales, 
        COUNT(*) as TOTAL FROM dairy as D
  LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile 
        WHERE source = 'Network' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1309561200
 group by D.Username order by TOTAL DESC

如您所见,它计算了 Yes、No、Other 和匹配的 MobileNo (D.MobileNo = S.mobile) 销售的数量。

我尝试为类型、用户名、手机、MobileNO、CheckDate 和来源添加索引 - 性能并没有提高多少。

【问题讨论】:

  • CheckDate的格式是什么?
  • 你可以不使用函数更改查询以检查 CheckDate,因为使用此函数包装该列的索引不太有效,请查看stackoverflow.com/questions/95183/…
  • 你能发布SHOW CREATE TABLE diary的输出吗?销售也一样?然后,您的 SELECT 的输出,但前面有 EXPLAIN

标签: mysql sql database sql-optimization


【解决方案1】:

查询中需要注意的三点:

1。 `LEFT JOIN` 可能会给您带来性能问题。

但是,您需要它,因为D.MobileNo 的值可能不会出现在SELECT DISTINCT mobile FROM sales 中。任何其他解决方法(是的,有选项)很可能会降低性能。但观察下一项可能会提高你的表现。

2。确保键列中有索引:

  • D.type
  • S.mobile
  • D.MobileNo
  • D.用户名
  • D.Source
  • D.CheckDate

3。您可能在使用 `UNIX_TIMESTAMP(CheckDate)` 过滤时遇到问题

这可能是关键问题。您可能在使用UNIX_TIMESTAMP(CheckDate) 而不是CheckDate 进行过滤时遇到问题,特别是在Dairy 有大量记录的情况下。问题是即使你有一个CheckDate 的索引,它也可能因为这个函数而不会被使用。尝试按CheckDate 本身过滤。

【讨论】:

  • 感谢 SQL 查询,它似乎不起作用 - 我没有得到任何结果。
  • 对不起,它现在可以工作了,我的错误......但结果似乎不同......它没有正确加起来。
  • 是否有可能存在 D.MobileNo 包含不在SELECT DISTINCT mobile FROM sales 中的值?
【解决方案2】:

如果这是时间紧迫的,那么存储更多数据也是有意义的。

这意味着您在应用程序中为 YesValue、NoValue、OtherValue 添加 INT 列并用 0 或 1 填充它们。通过这样做,您可以从 SELECT 部分中删除案例计算。

另外,请发布所有当前可用的索引,正如 cmets 所说的表的 CREATE 语句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    相关资源
    最近更新 更多