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,其中一个人甚至比较执行计划,发现它们是等效的。
答案 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
是最佳实践,所以这似乎很可能成为“神话”的来源。