简体   繁体   English

如何在SQL Server上优化以下更新查询?

[英]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条记录)运行此更新:

  1. All indexes disabled 所有索引均已禁用
  2. All 8 indexes enabled 全部启用8个索引
  3. All indexes disabled except the special one what intended to speedify the update: 除特殊索引(旨在加快更新速度)外,所有索引均被禁用:

create index idx0 on dbo.TargetTable (Id1, Id2, Id3) include (TargetValue) 在dbo.TargetTable(Id1,Id2,Id3)上创建索引idx0包括(TargetValue)

I get the following timings: 我得到以下计时:

  1. 7 minutes 7分钟
  2. 5 minutes 5分钟
  3. 53 seconds 53秒

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM