日期:2014-05-17  浏览次数:20496 次

求高手解惑,语句性能比较
在做项目时,碰到一个句子,感觉有点意思,但具体性能比较,哪个好就不知道了,求高手解惑。贴码:
SQL code

SELECT  * FROM TEST
WHERE 主键 NOT IN
(
SELECT 主键 FROM TEST
WHERE ColumnA='A' AND ColumnB='B'
)



SQL code

SELECT  * FROM TEST
WHERE NOT (ColumnA='A' AND ColumnB='B')



SQL code

SELECT * FROM TEST
WHERE ((ColumnA='A' AND ColumnB<>'B')
    OR (ColumnA<>'A' AND ColumnB<>'B')
    OR (ColumnA<>'A' AND ColumnB='B')
)



------解决方案--------------------
SELECT * FROM TEST
WHERE ((ColumnA='A' AND ColumnB<>'B')
OR (ColumnA<>'A' AND ColumnB<>'B')
OR (ColumnA<>'A' AND ColumnB='B')
)

这个理论上会好一点,因为上面两个都会造成表扫描
------解决方案--------------------
SELECT 主键 FROM TEST
WHERE ColumnA='A' AND ColumnB='B'

这个数据量不多的话,比如得到几十个几百个id的话
第一个方案最优

如果会很多那么修改会not exists
SQL code

select * from  TEST as a
where not exists (select 1 from TEST
WHERE ColumnA='A' AND ColumnB='B' and 主键=a.主键)

------解决方案--------------------
SQL code

--最好的解决方法
declare @StartTime datetime
set @StartTime = getdate()
[你的SQL 语句]

select datediff(ms,@StartTime,getdate())
--时间最小,语句最优

------解决方案--------------------
同意2楼,因为带exit量词的相关子查询只关心内层查询是否有返回值,并不需要查询具体值,因此效率可能会比不相关子查询高
------解决方案--------------------
not exists其实也会做表扫描,它是算为“不可参数化”的样式。
------解决方案--------------------
探讨
not exists其实也会做表扫描,它是算为“不可参数化”的样式。

------解决方案--------------------
做一个测试来说明这个观点
SQL code

--用于生成示例数据,这里是100W条数据
if OBJECT_ID('Test') is not null drop table Test
create table Test(ID [bigint] identity primary key,
  ColumnA char(1) NULL,     
  ColumnB char(1) NULL)
INSERT INTO dbo.Test SELECT  case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end, case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end

DECLARE @i AS INT, @rc AS INT,@max int;
SET @rc = 1;
SET @max = 1000000;
set @i = ceiling(log10(@max)/LOG10(2))-1;
WHILE @rc  <= @i
BEGIN
    INSERT INTO dbo.Test SELECT  case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end, case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end
  FROM dbo.Test;
  SET @rc = @rc +1 ;
END
select @max = @max - @@IDENTITY
INSERT INTO dbo.Test 
  SELECT top(@max) case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end, case 
when abs(checksum(newid()))%(3) = 0 then char(65+abs(checksum(newid()))%(26)) 
when abs(checksum(newid()))%(2) = 0 then char(97+abs(checksum(newid()))%(26)) end  FROM dbo.Test

------解决方案--------------------