我有以下查询:
SELECT * FROM (SELECT 'id_name_str' AS Id) t1
LEFT JOIN ( ... ) t2
ON t1.Id = t2.Id
这需要3毫秒才能运行。
但是,如果我执行以下操作需要很长时间(我在15分钟后退出查询)
create table #idtable
(
Id varchar(16) not null PRIMARY KEY
)
insert into #idtable(Id)
select Id
from (SELECT 'id_name_str' as Id)
SELECT * FROM (SELECT Id FROM #idtable) t1
LEFT JOIN ( ... ) t2
ON t1.Id = t2.Id
左连接正在对100,000个Ids和10万个行进行大量处理。
但是我在上面给出的情景中发生了什么?
答案 0 :(得分:1)
我刚在SQL Server 2008 R2上运行它:
create table #idtable
(
Id varchar(16) not null PRIMARY KEY
)
insert into #idtable(Id)
select Id
from (SELECT 'id_name_str' as Id) x1
create table dbo.t2 (t2 varchar(16), id1 int identity)
create table dbo.t2 (id varchar(16), id1 int identity)
insert into dbo.t2 values ('abc'),('def'), ('id_name_str')
go 5000
;
SELECT * FROM (SELECT Id FROM #idtable) t1
LEFT JOIN ( select * from t2) t2
ON t1.Id = t2.Id
insert / go 5000需要一段时间(应该使用交叉连接)但是select接近0时间。注意我必须在左连接中添加一个表别名。
注意我没有创建一个密钥(在现实生活中会有聚集的t2),但速度非常快。您对问题的描述缺少一些至关重要的内容。
我也认为SELECT * FROM(SELECT Id FROM #idtable)t1 LEFT JOIN(从t2中选择*)t2 ON t1.Id = t2.Id
与:
相同从#idtable t1左连接t2中选择t1.id,t2。*。
on t1.id = t2.id
所有子查询是什么?
答案 1 :(得分:0)
也许这样做(根据我上面的评论):
SELECT * FROM t2
WHERE t2.Id IN (SELECT Id From t1)
这将删除一般较慢的JOIN子句,在任何情况下,2个组合的SELECT语句在某种程度上是冗余的,因为只有反映另一个(然后连接),所以简化它
答案 2 :(得分:0)
SQL Server显然认为临时表中可能有更多行,然后确实存在。如果您运行它会有所帮助:
update statistics #idtable;
在执行主查询之前?
作为旁注,你使用的子查询比我更多。请考虑缩短此查询:
SELECT * FROM (SELECT Id FROM #idtable) t1
只是:
SELECT * FROM #idtable t1
而不是以下(对我来说看起来像语法错误,因为from
之后子查询没有别名):
insert into #idtable(Id)
select Id
from (SELECT 'id_name_str' as Id)
你可以写:
insert into #idtable(Id)
select 'id_name_str'
或者您可以省略列列表(默认为所有列),省略可选的into
,并使用values
子句代替select
:
insert #idtable
values ('id_name_str')