【问题标题】:Can I speedup this mysql query?我可以加快这个 mysql 查询吗?
【发布时间】:2013-06-23 13:23:52
【问题描述】:

部分查询是:

SELECT * FROM `o` WHERE ....
AND `id` IN     (SELECT DISTINCT `id` FROM `o` WHERE `activity` = '1' AND `date` < '20130310'                      ORDER BY `id` ASC)
AND `id` NOT IN (SELECT DISTINCT `id` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329' ORDER BY `id` ASC)
....

:在20130310之前有活动而在20130310 AND 20130329之间没有活动的ID

1) 我可以加速这个 mysql 查询吗?

2) 是否有助于ORDER BY 提高INNOT IN 的速度?

【问题讨论】:

  • 不需要通过命令使用命令
  • @Ankit 你有这方面的参考资料吗?
  • 为什么需要这个 order by 的引用是对选中记录进行排序的命令,在子查询中使用时不需要对选中记录进行排序。你可以自己试试通过删除它,您将看到查询结果没有任何变化

标签: mysql performance subquery query-optimization


【解决方案1】:

由于 MySQL 中的 IN() 子查询通常很慢(至少在 5.6 之前),因此您最好使用 join

SELECT * FROM `o`
LEFT JOIN
(SELECT `id` AS `idactive` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329') as t
USING `id`
WHERE `activity` = '1' AND `date` < '20130310' AND `idactive` IS NULL

【讨论】:

    【解决方案2】:

    你可以这样做

      SELECT * FROM `o` WHERE ....
      AND `id` IN     (SELECT DISTINCT `id` FROM `o` 
                       WHERE `activity` = '1' AND `date` < '20130310'   
                       ORDER BY `id` ASC)
    

    你不需要第二个 AND 因为你已经选择了 date &lt; 20130310 所以它不会选择 20130311 20130312 ...20130329

    或者你可以简单地做这个查询

        SELECT * FROM `o` WHERE ....
        AND `activity` = '1' AND `date` < '20130310'   
        GROUP BY `id` 
        ORDER BY `id` ASC
    

    【讨论】:

      【解决方案3】:

      如果id 是您的主键(应该是),那么您的两个与日期相关的子句之一是无用的(`date` &lt; '20130310' 总是暗示NOT (`date` BETWEEN '20130310' AND '20130329'),允许您将事情简化为:

      select *
      from o
      where activity = 1
      and date < '20130310'
      

      如果id 实际上是其他字段中的一个(在这种情况下,这是一个非常令人困惑的名称选择),它以 1-n 或 nm 关系引用单独的表,我假设您正在寻找对于至少有一个在日期范围内有活动但此后没有新活动的 ID。在这种情况下,您的查询可以简化为:

      SELECT * FROM `o` WHERE ....
      AND `id` IN     (SELECT `id` FROM `o` WHERE `activity` = '1' AND `date` < '20130310')
      AND `id` NOT IN (SELECT `id` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329')
      

      换句话说,distinctorder by 子句都是没有意义的。

      在任何一种情况下,如果相关,还请注意您的 date 字段应该是 date 类型,而不是 varchar 类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        • 1970-01-01
        • 2013-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多