[英]How to optimize the following update query on SQL Server?
I need to optimize the following update query on SQL Server 2005/2008: 我需要在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
)
About table dbo.TargetTable: it has about 100 columns and 8 non-clustered indexes. 关于表dbo.TargetTable:它具有约100列和8个非聚集索引。 None of the indexes is made of Id1, Id2, Id3 and includes TargetColumn. 索引均不由Id1,Id2,Id3构成,也不包含TargetColumn。
I tried to run this update on 3 combinations of indexes (size of table about 200000 records): 我尝试对3种索引组合(表大小约为200000条记录)运行此更新:
create index idx0 on dbo.TargetTable (Id1, Id2, Id3) include (TargetValue) 在dbo.TargetTable(Id1,Id2,Id3)上创建索引idx0包括(TargetValue)
I get the following timings: 我得到以下计时:
But then I tried this query on the table with size about 10 million records none of the cases was able to finish. 但是后来我在表上尝试了该查询,该表的大小约为1000万条记录,所有这些案例都无法完成。 In each case SQL server gave me strange errors about buffer pool running out of memory. 在每种情况下,SQL Server都会给我关于缓冲池内存不足的奇怪错误。
Are there any other ways to optimize this query apart from using the special index? 除了使用特殊索引以外,还有其他方法可以优化此查询吗?
I believe following update is equivalent... 我相信以下更新是等效的...
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
...and benefits from following 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)
Use a CTE to get the fastest performance: 使用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;
It may be useful for you, some time temporary table is very useful in speed. 这可能对您有用,某些时候临时表对速度非常有用。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.