练习“存在(从...选择1)”从哪里来?

绝大多数人支持我自己的观点,即下列陈述没有区别:

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或某些地方这是真的,但我找不到对此的参考。 所以,我很好奇 - 这种做法如何诞生? 这个神话起源于哪里?

补充:由于有些人坚持有证据表明这确实是一种错误的信念,在这里 - 一个谷歌查询显示很多人这样说。 如果你太懒惰,请检查这个直接链接,其中一个人甚至会比较执行计划,发现它们是相同的。


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

因此,为了回答这个问题,我想人们用sql学到的第一个性能提示就是select *在大多数情况下都是低效的。 因此,在这种特定情况下这种做法并不没有效率,因此有些违背直觉。 所以人们对此持怀疑态度并不奇怪。 但是一些简单的研究或实验应该足以驱散大多数的神话。 虽然人类历史有点显示神话很难消除。


作为演示,请尝试这些

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,第191页,案例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 - 插入如果不存在)这不适用于SQL Server 2000,但我知道它在SQL Server 2005+


对于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 并不回避此列扩展。 详细信息在这里。

链接地址: http://www.djcxy.com/p/32871.html

上一篇: Where does the practice "exists (select 1 from ...)" come from?

下一篇: Correct way to take a exclusive lock