如果我们有一个SQL视图VIEW_MYTABLE
,例如50列。
选项1 :
with CTE_MYQUERY1 as (
select [VIEW_MYTABLE].*
from [VIEW_MYTABLE]
/*some complex where clause*/
)
选项2 :
with CTE_MYQUERY2 as (
select [COLUMN_1], [COLUMN_2], [COLUMN_3], ...., [COLUMN_10]
from [VIEW_MYTABLE]
/*some complex where clause*/
)
根据我的理解,定义列的select总是比select *
语句快。请注意,在第二个查询中,我只选择视图中50列中的10列。
我得到的结果都一样吗?任何人都可以让我知道CTE如何在内部工作,它首先生成结果集,然后将其提供给后续查询(在我的情况下为SELECT
查询)?
答案 0 :(得分:7)
我希望这两个查询之间的运行时间完全没有明显区别。
但是,我仍然会提倡反对 SELECT *,而不是出于性能原因。有一个长期存在的神话,SELECT *的效率较低,因为引擎必须查找元数据中的列名,但事实是仍然存在验证列名称的查找你已经写好了,无论结果集大小如何,人们都不会注意到检索这些名字的额外费用。
我提倡反对SELECT *的原因是:
您不太可能需要表格中的所有列(或所有行,但这是一个不同的故事)。如果要删回的列多于您需要的列数,那么您正在执行不必要的I / O,并且可能会强制SQL Server执行表/聚簇索引扫描,因为它可以在更精简的索引上执行扫描。
即使您确实需要所有列,使用SELECT *也会在以后的代码中导致难以检测的问题。如果有人在表格中间插入一列,该怎么办?删掉一列?添加一列?重命名一列?其中一些将立即被捕获,但我已经证明了这可能导致各种难以调试的问题。
至于CTE如何运作,这是一个非常广泛的问题。我从这些文章开始:
http://www.simple-talk.com/sql/t-sql-programming/sql-server-cte-basics/
https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008/ms190766(v=sql.100)
答案 1 :(得分:1)
主要方式SELECT *
可能会影响性能,这会导致查询浪费时间来检索比实际需要更多的数据。但是查询主要部分中的SELECT
子句决定了检索哪些数据。*(非递归)公用表表达式可以被认为是一种一次性视图。 CTE中未使用它的查询中引用的任何列最终都会被忽略。与查询视图时的方式类似,引擎不一定会抓取视图中的每一列,只是您要求的每一列。
我的猜测是,你在两个CTE中都获得了相同的性能,因为使用它们的查询(在示例中省略了)在两种情况下都是相同的。因此,第一个选项中引用的额外列不会对完整查询检索到的数据产生任何影响。
*已添加:为清楚起见,这只是SELECT
的情况。 WHERE
和JOIN
子句会影响哪些列必须在哪里出现。
答案 2 :(得分:0)
不要将绝对必要的更多列或行数据返回给客户端。这只会增加服务器上的磁盘I / O和网络流量,这两者都会影响性能。在SELECT
语句中,不要使用SELECT *
来返回行,请始终在SELECT
语句中指定需要为此特定查询返回哪些列,而不是更多列。在大多数情况下,请确保包含WHERE
子句,以减少发送到客户端立即执行任务所需行的数量或行数。
在我看来,最重要的区别在于你的复杂WHERE
条款,主要行动发生在哪里,涉及索引等等。
所有这一切,我相信第二个将在几乎所有场景中表现更好。
请Steve Jones on SQL Central查看此详细文章。