Sergey Soloviev
Sergey Soloviev

Reputation: 51

How to optimize the following update query on SQL Server?

I need to optimize the following update query on 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. None of the indexes is made of Id1, Id2, Id3 and includes TargetColumn.

I tried to run this update on 3 combinations of indexes (size of table about 200000 records):

  1. All indexes disabled
  2. All 8 indexes enabled
  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)

I get the following timings:

  1. 7 minutes
  2. 5 minutes
  3. 53 seconds

But then I tried this query on the table with size about 10 million records none of the cases was able to finish. In each case SQL server gave me strange errors about buffer pool running out of memory.

Are there any other ways to optimize this query apart from using the special index?

Upvotes: 5

Views: 2217

Answers (3)

Dave Hilditch
Dave Hilditch

Reputation: 5439

Use a CTE to get the fastest performance:

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;

Upvotes: 0

KuldipMCA
KuldipMCA

Reputation: 3149

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

Upvotes: 0

Lieven Keersmaekers
Lieven Keersmaekers

Reputation: 58431

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)

Upvotes: 5

Related Questions