IN vs NOT EXISTS子句,查询优化

时间:2015-03-03 08:08:14

标签: sql optimization

以下是示例的简化表:

my tables

这是我的疑问:

  

SELECT * FROM article A

     

在哪里A.id IN(

     

从文章A1,article_tag AT

中选择AT.article_id      

WHERE(A1.id = AT.article_id)

     

AND(AT.tag_id IN (2,1)

     

GROUP BY AT.article_id

     

有计数(AT.article_id)= 2

     

);

从技术上讲,此查询似乎有效并返回 "all the articles having at least keywords 2 and 1"

大胆的部分是要改变的。例如,如果我的关键字列表是[1,3,4],

(2, 1)将更改为(1,3,4)2将更改为 3 (列表的长度)。

虽然这个查询确实有用,但我稍微记得一个朋友使用 NOT EXISTS 子句。适用吗?如果是,哪个查询是性能方面的最佳优化?

3 个答案:

答案 0 :(得分:2)

您不需要EXISTS或IN - 只需GROUP BY文章中的所有列,您就完成了。示例(在Oracle语法中,因为您没有提到您的RDBMS):

with article(id, title) as (
    select 1, 'MS SQL Server' from dual union all
    select 2, 'Oracle' from dual union all
    select 3, 'PostgreSQL' from dual union all
    select 4, 'IDBM DB2' from dual),
  article_tag(id, article_id, tag_id) as (
    select 1,1,1 from dual union all
    select 2,1,2 from dual union all
    select 3,2,1 from dual union all
    select 4,3,2 from dual
  ) 
  SELECT a.id, a.title 
  FROM article a
  JOIN article_tag at ON a.id = at.article_id
       AND at.tag_id IN (2,1)
  GROUP BY a.id, a.title
  HAVING COUNT(at.article_id) = 2;

答案 1 :(得分:1)

  

如果是,哪个查询在性能方面是最佳优化?

优化sql时,您唯一的朋友是查询计划并打开统计信息。结果通常取决于表中的数据。在查询计划中,您可以看到sql-server在某些表上执行的操作,使用统计信息可以查看原始计时和读取。

查看查询时,您可以创建内部联接,EXISTS,IN,表值函数,内联表值函数等。在许多情况下,sql server会将它们优化为相同的查询计划。但是在某些情况下它没有。首先进行查询并查看需要哪些索引,在许多情况下,索引比编写查询的方式更重要。

优化SQL查询的关键是使用实际数据和实际参数。然后测量,测量,测量和分析IO /读数/计时等。

答案 2 :(得分:0)

我可以看到的一个问题是数据库无法重用查询计划,因为对于不同的参数,您正在更改查询文本。这通常会导致次优的查询计划。

因此,不要考虑inexists,而应考虑将选项作为参数传递。您没有指定您正在使用的数据库引擎,所以我不能说具体的内容。例如,在MS SQL上,您可以使用表参数或xml参数来执行此操作,从而帮助查询计划程序完成其工作。

还可以使用一些技巧来使查询更直接,但这只是关于如何使用查询以及如何执行查询的具体统计信息。

警惕轶事证据 - 很多反对使用in (subquery)和类似论点的论点已有数年之久,不再需要适用于您的场景。测量。准备真实的测试数据。测量。猜测伤害:)