选择前1*vs选择前1 1

Sto*_*orm 7 t-sql sql-server database-performance

我知道有很多这些问题,但我找不到与我的问题有关的问题.

看看这个问题,将IF EXIST(SELECT 1 FROM)更改为IF EXIST(SELECT TOP 1 FROM)是否有任何副作用?

在答案中特别提到这一节:

select * from sys.objects
select top 1 * from sys.objects
select 1 where exists(select * from sys.objects)
select 1 where exists(select top 1 * from sys.objects)
Run Code Online (Sandbox Code Playgroud)

我正在运行一些自己的测试来正确理解它.如答案所示:

select 1 where exists(select top 1 * from sys.objects)
select 1 where exists(select top 1 1 from sys.objects)
Run Code Online (Sandbox Code Playgroud)

两者都导致相同的执行计划,并导致相同的计划

select 1 where exists(select * from sys.objects)
select 1 where exists(select 1 from sys.objects)
Run Code Online (Sandbox Code Playgroud)

从我对这个问题的研究,"SELECT TOP 1 1"VS"IF EXISTS(SELECT 1".我推断这是商定的最佳实践:

select 1 where exists(select * from sys.objects)
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是为什么这比这更受欢迎:

select 1 where exists(select 1 from sys.objects)
Run Code Online (Sandbox Code Playgroud)

在试图理解它时,我将它们分解为更基本的表达式(我使用'前1'来模仿类似存在的执行计划):

select top 1 * from sys.objects
select top 1 1 from sys.objects
Run Code Online (Sandbox Code Playgroud)

我现在看到第一个是执行时间的80%(相对于批次为2),而第二个只有20%.那么使用它会不是更好的做法

select 1 where exists(select 1 from sys.objects)
Run Code Online (Sandbox Code Playgroud)

因为它可以应用于两种情况,从而减少可能的人为错误?

Rog*_*olf 9

SQL Server EXISTS在查询编译/优化过程中相对较早地检测谓词,并消除了对这些子句的实际数据检索,将其替换为存在检查.所以你的假设:

我现在看到第一个是执行时间的80%(相对于批次为2),而第二个只有20%.

是错误的,因为在前面的比较中,您实际上已经检索了一些数据,如果将查询放入(not) exists谓词中,则不会发生这种情况.

大多数时候,除了一个重要的捕获之外,如何测试行的存在没有区别.假设你说:

if exists (select * from dbo.SomeTable)
...
Run Code Online (Sandbox Code Playgroud)

代码模块中的某个地方(视图,存储过程,函数等).然后,当其他人决定将WITH SCHEMABINDING子句放入此代码模块时,SQL Server将不允许它,而不是可能绑定到当前列列表,它将引发错误:

消息1054,级别15,状态7,过程BoundView,第6行
语法绑定对象中不允许使用语法'*'.

简而言之:

if exists (select 0 from ...)
Run Code Online (Sandbox Code Playgroud)

是一种最安全,最快速,最适合所有存在检查的方式.


Jam*_*s Z 5

这两者的区别:

select top 1 * from sys.objects
select top 1 1 from sys.objects
Run Code Online (Sandbox Code Playgroud)

在第一个子句中,SQL Server 必须从表中获取所有列(从任何随机行),但在第二个子句中,可以从任何索引中获取“1”。

当这些子句位于exists子句内时,情况会发生变化,因为在这种情况下,SQL Server 知道它实际上不必获取数据,因为它不会分配给任何内容,因此它可以以与select *处理select 1.

由于存在仅检查一行,因此它内置了内部 top 1,因此手动添加它不会改变任何内容。

存在子句中的“天气”select *select 1“天气”仅基于意见,您当然可以使用 2 或“X”或任何您喜欢的内容来代替 1。我个人总是使用... and exists (select 1 ...