在性能方面,如果我有一个WHERE子句,如a = 0和b = 0,并且… z = 0,如果我用b … z = 0替换该条件,我会获得任何性能吗?
Select * From MyTable Where A=0 and B=0 and C=0 and D=0...
同
Select * From MyTable Where A+B+C+D=0...
我知道它可以依赖于索引,但为了这个目的,我们只说没有索引存在.算术运算符()的性能是否优于“OR”或“AND”逻辑运算符?
我的印象是,添加比使用AND或OR的多个条件更好.
检测结果
在一个420万行的表上
返回行,其中A = 0 B = 0且C = 0 – > 351748行
加法(A B C = 0)花费5秒,而逻辑条件A = 0且B = 0且C = 0花费11秒.
另一方面
返回行其中A<> 0< 0> 0或C< 0>> 3829750行58秒
返回行F65 F67 f64<> 0 – > 3829750行57秒
对于OR,似乎没有显着差异.
我同意gbn:
If A is -1 and B is 1,A+B=0 but A=0 and B= 0 is false
和AMtwo:
ABS(A)+ABS(B)+ABS(C)+ABS(D)… Even if you expect only positive values,if the column accepts negative values,you should assume that you might encounter one
结果非常令人印象深刻,正如我想的那样,似乎加法比逻辑运算符快得多.
A = Float,B = Money和C = Float.使用的查询如图所示.就我而言,所有都是正数.没有索引.在我看来,合乎逻辑的是,添加会比逻辑条件更快!
解决方法
首先,您需要确保不测试sql Server Management Studio(或您正在使用的任何客户端).例如,如果从具有300万行的表中运行SELECT *,则主要测试SSMS从sql Server中提取行并在屏幕上呈现它们的能力.使用像SELECT COUNT(1)这样的东西要好得多,这样就无需在网络上抽取数百万行,并在屏幕上渲染它们.
其次,您需要了解sql Server的数据缓存.通常,我们测试从存储中读取数据的速度,以及从冷缓存(即sql Server的缓冲区为空)处理该数据的速度.有时,使用热缓存进行所有测试是有意义的,但是您需要明确地考虑这一点来进行测试.
对于冷缓存测试,您需要在每次运行测试之前运行CHECKPOINT和DBCC DROPCLEANBUFFERS.
对于您在问题中询问的测试,我创建了以下测试平台:
IF COALESCE(OBJECT_ID('tempdb..#SomeTest'),0) <> 0 BEGIN DROP TABLE #SomeTest; END CREATE TABLE #SomeTest ( TestID INT NOT NULL PRIMARY KEY IDENTITY(1,1),A INT NOT NULL,B FLOAT NOT NULL,C MONEY NOT NULL,D BIGINT NOT NULL ); INSERT INTO #SomeTest (A,B,C,D) SELECT o1.object_id,o2.object_id,o3.object_id,o4.object_id FROM sys.objects o1,sys.objects o2,sys.objects o3,sys.objects o4; SELECT COUNT(1) FROM #SomeTest;
这将在我的机器上返回260,144,641的计数.
CHECKPOINT 5; DBCC FREEPROCCACHE; DBCC DROPCLEANBUFFERS; SET STATISTICS IO,TIME ON; GO SELECT COUNT(1) FROM #SomeTest st WHERE (st.A + st.B + st.C + st.D) = 0; GO SET STATISTICS IO,TIME OFF;
消息选项卡显示:
Table ‘#SomeTest’. Scan count 3,logical reads 1322661,physical reads 0,read-ahead reads 1313877,lob logical reads 0,lob physical reads 0,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 49047 ms,elapsed time = 173451 ms.
对于“离散列”测试:
CHECKPOINT 5; DBCC FREEPROCCACHE; DBCC DROPCLEANBUFFERS; SET STATISTICS IO,TIME ON; GO SELECT COUNT(1) FROM #SomeTest st WHERE st.A = 0 AND st.B = 0 AND st.C = 0 AND st.D = 0; GO SET STATISTICS IO,TIME OFF;
再次,从消息选项卡:
Table ‘#SomeTest’. Scan count 3,read-ahead reads 1322661,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 8938 ms,elapsed time = 162581 ms.
从上面的统计数据可以看到第二个变量,离散列与0相比,经过的时间缩短了大约10秒,cpu时间减少了大约6倍.我上面的测试中的长持续时间主要是从磁盘读取大量行的结果.如果将行数减少到300万,您会看到比率保持大致相同但经过的时间明显减少,因为磁盘I / O的影响要小得多.
使用“加法”方法:
Table ‘#SomeTest’. Scan count 3,logical reads 15255,read-ahead reads 0,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 499 ms,elapsed time = 256 ms.
使用“离散列”方法:
Table ‘#SomeTest’. Scan count 3,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 94 ms,elapsed time = 53 ms.
什么会对这个测试产生非常大的影响?适当的索引,例如:
CREATE INDEX IX_SomeTest ON #SomeTest(A,D);
Table ‘#SomeTest’. Scan count 3,logical reads 14235,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 546 ms,elapsed time = 314 ms.
“离散列”方法:
Table ‘#SomeTest’. Scan count 1,logical reads 3,lob read-ahead reads 0.
sql Server Execution Times:
cpu time = 0 ms,elapsed time = 0 ms.
每个查询的执行计划(使用上述索引就位)非常有说服力.
和“离散列”方法,它可以寻找前导索引列A为零的索引的第一行: