我需要在SQL Server 2005/2008上优化以下更新查询:
UPDATE
dbo.TargetTable A
SET
TargetColumn = 0
WHERE
TargetColumn = 1
AND 1 =
(
SELECT COUNT(*)
FROM dbo.TargetColumn B
WHERE
A.Id1 = B.Id1
AND A.Id2 = B.Id2
AND A.Id3 = B.Id3
)
关于表dbo.TargetTable:它有大约100列和8个非聚簇索引。没有索引由Id1,Id2,Id3组成,并且包括TargetColumn。
我尝试在3种索引组合上运行此更新(表大小约为200000条记录):
在dbo上创建索引idx0.TargetTable(Id1,Id2,Id3)include(TargetValue)
我得到以下时间:
然后我在桌子上尝试了这个查询,大小大约有1000万条记录,没有一个案例能够完成。在每种情况下,SQL服务器都给出了关于缓冲池内存不足的奇怪错误。
除了使用特殊索引外,还有其他方法可以优化此查询吗?
答案 0 :(得分:5)
我相信以下更新是等效的......
UPDATE dbo.TargetTable
SET TargetColumn = 0
FROM dbo.TargetTable A
INNER JOIN (
SELECT A.Id1
, A.Id2
, A.Id3
FROM dbo.TargetTable A
INNER JOIN dbo.TargetColumn B ON A.Id1 = B.Id1
AND A.Id2 = B.Id2
AND A.Id3 = B.Id3
GROUP BY
A.Id1
, A.Id2
, A.Id3
HAVING COUNT(*) = 1
) B ON B.Id1 = A.Id1
AND B.Id2 = A.Id2
AND B.Id3 = A.Id3
WHERE A.TargetColumn = 1
...以及以下Covering Indexes
带来的好处CREATE INDEX IX_TARGETTABLE_ID1_ID2_ID3 ON dbo.TargetTable (Id1, Id2, Id3) INCLUDE (TargetColumn)
CREATE INDEX IX_TARGETCOLUMN_ID1_ID2_ID3 ON dbo.TargetColumn (Id1, Id2, Id3)
答案 1 :(得分:0)
它可能对您有用,有时候临时表在速度上非常有用。
select count(*) as cnt,A.ID1,A.ID2,A.ID3 into #Temp from TargetTable as A
group by A.ID1,A.ID2,A.ID3
having Count(*) = 1
UPDATE
dbo.TargetTable A
SET
TargetColumn = 0
From #Temp B
WHERE
TargetColumn = 1
and A.Id1 = B.Id1
AND A.Id2 = B.Id2
AND A.Id3 = B.Id3
答案 2 :(得分:0)
使用CTE获得最快的性能:
create table #a (id1 int, id2 int, id3 int, targetcolumn int);
create table #b (id1 int, id2 int, id3 int);
with rowstoupdate as (
select #a.targetcolumn, count(*) over(partition by #a.id1, #a.id2, #a.id3) totalnum
from #a inner join #b
on #a.id1 = #b.id1
and #a.id2 = #b.id2
and #a.id3 = #b.id3
)
update rowstoupdate
set targetcolumn = 0
where targetcolumn = 1
and totalnum = 1;