我可以加快这个mysql查询吗?

时间:2013-06-26 12:04:07

标签: mysql performance subquery query-optimization

查询的一部分是:

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和20130329之间没有活动的ID

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

2)帮助ORDER BY帮助提高INNOT IN的速度吗?

3 个答案:

答案 0 :(得分:2)

由于IN()子查询在MySQL中通常很慢(至少在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

答案 1 :(得分:0)

你可以这样做

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

你不需要第二个AND因为你已选择date < 20130310所以它不会选择20130311 20130312 ... 20130329

您只需执行此查询

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

答案 2 :(得分:0)

如果id是您的主键(应该是),那么您的两个与日期相关的子句中的一个是无用的(`date` < '20130310'总是暗示NOT (`date` BETWEEN '20130310' AND '20130329'),这样可以简化事情到:

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

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

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类型。