实践“存在(从...中选择1)”来自何处?

时间:2011-05-26 10:58:22

标签: sql history

overwhelming majority of people support我自己认为以下陈述没有区别:

SELECT * FROM tableA WHERE EXISTS (SELECT * FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT y FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT NULL FROM tableB WHERE tableA.x = tableB.y)

然而今天,在我们的内部开发人员会议上,我提出了select 1是要走的路,而select *选择所有(不必要的)数据时,我面对面地反对相反的主张。因而伤害了表现。

我似乎记得有一些旧版本的Oracle或其他地方都是如此,但我找不到对它的引用。所以,我很好奇 - 这种做法是如何诞生的?这个神话来自哪里?

已添加:由于some people坚持要证明这确实是一种错误的信念,所以这里有一个google query,显示有很多人这么说。如果你太懒,请检查this direct link,其中一个人甚至比较执行计划,发现它们是等效的。

4 个答案:

答案 0 :(得分:23)

你问题的主要部分是 - “这个神话来自哪里?”

所以回答这个问题,我想人们用sql学习的第一个性能提示之一就是select *在大多数情况下是低效的。因此特定情况下效率不高的事实在某种程度上是违反直觉的。所以人们对它持怀疑态度并不奇怪。但是一些简单的研究或实验应该足以消除大多数神话。虽然有点人类历史表明神话很难被驱逐。

答案 1 :(得分:13)

作为演示,请尝试这些

SELECT * FROM tableA WHERE EXISTS (SELECT 1/0 FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT CAST('bollocks' as int) FROM tableB WHERE tableA.x = tableB.y)

现在阅读ANSI标准。 ANSI-92, page 191, case 3a

If the <select list> "*" is simply contained in a <subquery>
          that is immediately contained in an <exists predicate>, then
          the <select list> is equivalent to a <value expression> that
          is an arbitrary <literal>.

最后,大多数RDBMS上的行为应该忽略EXISTS子句中的THE *。根据昨天的这个问题(Sql Server 2005 - Insert if not exists),这不适用于SQL Server 2000,但我知道它在SQL Server 2005 +上运行

答案 2 :(得分:4)

来自查询优化工具小组的

For SQL Server Conor Cunningham解释了他通常使用SELECT 1

的原因
  

QP将采取并扩展所有*   在管道的早期并将它们绑定到   对象(在这种情况下,列表   列)。然后它会删除   由于性质的原因,不需要的列   查询。

     

因此对于一个简单的EXISTS子查询   这样:

     

SELECT col1 FROM MyTable WHERE EXISTS   (SELECT * FROM Table2 WHERE   MyTable.col1 = Table2.col2)*将是   扩展到一些潜在的大   列列表然后它将是   确定了语义   EXISTS不要求任何这些   列,所以基本上所有这些都可以   被删除。

     

“SELECT 1”将避免   检查任何不需要的元数据   查询编译期间的表。

     

但是,在运行时这两种形式   查询将是相同的,并将   有相同的运行时间。

编辑但是,自从发布此答案并得出结论SELECT 1 以避免此列扩展后,我已详细研究了这一点。 Full details here

答案 3 :(得分:0)

这个问题的答案是,MS Access的某些版本实际上并没有忽略SELECT子句的字段。我已经完成了一些Access开发,我听说SELECT 1是最佳实践,所以这似乎很可能成为“神话”的来源。

Performance of SQL EXISTS usage variants