使用NOT IN查询然后用IN查询?

时间:2016-01-27 12:29:29

标签: mysql performance

让我们假设以下简单的情况:

我有两个表,一个类别表,其中包含两个字段CategoryIdCategoryGroup,以及一个包含另一个字段的广告表两个字段AdIdcategory_CategoryId,它是指向类别表的链接。

类别表格中的所有行都分为两个不同的组:购买租借。因此,该表中的每一行都在CategoryGroup中包含字符串 buy 或字符串 rent

假设我想计算出售广告中的广告数量。

我有两种方法可以做到这一点:

  1. 执行NOT IN这样的查询:SELECT COUNT(AdId) as Total FROM ads WHERE category_CategoryId NOT IN (SELECT CategoryId FROM category WHERE CategoryGroup = 'rent')

  2. 或者像这样执行'IN'查询:SELECT COUNT(AdId) as Total FROM ads WHERE category_CategoryId IN (SELECT CategoryId FROM category WHERE CategoryGroup = 'buy')

  3. 我测试了两个查询,在我看来,NOT IN查询的执行速度比IN类型的查询快。

    (约{900}表上NOT IN为0.45秒,约45个类别,同一数据集上IN为1.1秒

    这是偶然的,或者NOT IN查询在相似的情况下总能执行得更快吗?

1 个答案:

答案 0 :(得分:0)

IN ( SELECT ... )NOT IN ( SELECT ... )可能永远是编写内容的最有效方式。一个可能比另一个更快,因为SELECT的行数少于另一个,而不是NOT

假设广告只属于一个类别,这可能是效率最高的。

SELECT  Count(ads.AdId) as Total, ads.CategoryId
    FROM  ads
    JOIN  category AS c ON c.CategoryId = ads.CategoryId
    WHERE  c.CategoryGroup = 'buy'
    GROUP BY  ads.CategoryId 

如果某个广告可以分为多个类别,那么您就会有一个难题:是否应该在计数中包含或排除“买入”和“出租”的广告?无论如何,我正准备将IN替换为EXISTS作为替代优化:

SELECT  Count(AdId) as Total, CategoryId
    FROM  ads
    WHERE  EXISTS 
      ( SELECT  *
            FROM  category
            WHERE  CategoryId = ads.CategoryId
              AND  CategoryGroup = 'buy' 
      )
    GROUP BY  CategoryId 

(抱歉,我不能忍受像category_CategoryId这样不必要的冗余列名。)

对各种选择执行EXPLAIN SELECT ...以获得更多洞察力。