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

哪个效率高,查询表a在表b存在的数据?
哪个效率高,查询表a在表b存在的数据?假设表b的数据比较多,查询出来的结果可以重复的
select a.* from a,b where a.id=b.id 查询出的结果有可能重复
select *from a where a.id in (select b.id from b)
select*from a where exist(select*from b where a.id=b.id)
以上哪个效率高?

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


/************************************************
真心不希望看到“我认为”“我感觉”“估计”“应该”
虽然我的测试有自己的前提,结论也不一定完全正确
实际上我也不会去下结论
*************************************************/
create table tableTestA
(
id int ,
Name varchar(50),
Number varchar(50),
Remark varchar(200)
)
go
create table tableTestB
(
    id int ,
Name varchar(50),
Number varchar(50),
Remark varchar(200)
)
go
create unique clustered index IX_ID on tableTestA(id)
go
create unique clustered index IX_ID on tableTestB(id)
go

truncate table tableTestA

declare @i int 
set @i=0
while(@i<500000)
begin
if(@i%10=0)--按照楼主的要求,A,B表比例为1:10,5000和500000的数据量
begin
insert into tabletestA values(@i,newid(),newid(),newid())
end
insert into tabletestB values(@i,newid(),newid(),newid())
set @i=@i+1
end
go


dbcc dropcleanbuffers


set statistics io on 
set statistics profile on
select A.* from tableTestA A inner join tableTestB B on A.id=B.id

--(50000 行受影响)
--表 'tableTestB'。扫描计数 1,逻辑读取 8102 次,物理读取 31 次,预读 8089 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 'tableTestA'。扫描计数 1,逻辑读取 812 次,物理读取 1 次,预读 319 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。



select * from tableTestA where id in (select id from tableTestB)

--(50000 行受影响)
--表 'tableTestB'。扫描计数 1,逻辑读取 8102 次,物理读取 24 次,预读 8089 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 'tableTestA'。扫描计数 1,逻辑读取 812 次,物理读取 1 次,预读 319 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。



select * from tableTestA A where exists(select 1 from tableTestB B where A.id=B.id )


--(50000 行受影响)
--表 'tableTestB'。扫描计数 1,逻辑读取 8102 次,物理读取 37 次,预读 8089 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--表 'tableTestA'。扫描计数 1,逻辑读取 812 次,物理读取 1 次,预读 319 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。



------解决方案--------------------
根据表上的实际数据量和索引情况,最终生成的计划会有不同,一般来说是写的大表in小表,小表exists大表。
join有写法不推荐,在某些情况下会多一步无意义的键查找。
如果外面是小表,exists的写法需要在内表用来连接的键上建个索引,这样计划走索引查询会避免全表扫描。
如果里外的表都很大,这几个查询没什么区别,生成的计划应该是一样的哈希或合并连接。