Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 SQL Server Administration (2008)
 Sub-optimal query plan?

Author  Topic 

Kristen
Test

22859 Posts

Posted - 2013-12-14 : 00:49:04
Any ideas why non-unique IX_UpdateDate used rather than unique Primary Key PK_MyTable ? (Or would it not make any difference?)

CREATE TABLE [dbo].[MyTable]
(
[MyUpdateDate] [datetime] NOT NULL,
[MyStatus] [tinyint] NULL,
[MyPKey] [varchar](17) COLLATE Latin1_General_CI_AS NOT NULL,
... 153 other columns ...
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[MyPKey] ASC
)
)

CREATE NONCLUSTERED INDEX [IX_UpdateDate] ON [dbo].[MyTable]
(
[MyUpdateDate] ASC
)

CREATE TABLE ##MyTempTable
(
[MyPKey] varchar(17) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
... 157 other columns ...
PRIMARY KEY
(
MyPKey
)

)

INSERT INTO ##MyTempTable
... 1,567,783 rows ...


INSERT dbo.MyTable
SELECT
[MyUpdateDate] = GetDate(),
[MyStatus] = 1,
S.*
FROM ##MyTempTable AS S
WHERE NOT EXISTS
(
SELECT *
FROM dbo.MyTable AS D
WHERE S.MyPKey = D.MyPKey COLLATE SQL_Latin1_General_CP1_CI_AS
)
ORDER BY S.MyPKey

NOTE: All the rows already exist, so there are NO actual insertions

Query Plan:
|--Clustered Index Insert(OBJECT:([MyDB].[dbo].[MyTable].[PK_MyTable]), OBJECT:([MyDB].[dbo].[MyTable].[IX_UpdateDate]),
SET:([MyDB].[dbo].[MyTable].[MyUpdateDate] = RaiseIfNullInsert([Expr1008]),[MyDB].[dbo].[MyTable].[MyStatus] = [Expr1010],
[MyDB].[dbo].[MyTable].[MyPKey] = [tempdb].[dbo].[##MyTempTable].[MyPKey] as [S].[MyPKey],...
|--Compute Scalar(DEFINE:([Expr1008]=getdate(), [Expr1010]=CONVERT_IMPLICIT(tinyint,(1),0)))
|--Top(ROWCOUNT est 0)
|--Sort(ORDER BY:([S].[MyPKey] ASC))
|--Hash Match(Right Anti Semi Join, HASH:([Expr1013])=([Expr1012]), RESIDUAL:([Expr1012]=[Expr1013]))
|--Hash Match(Aggregate, HASH:([Expr1013]), RESIDUAL:([Expr1013] = [Expr1013]))
| |--Compute Scalar(DEFINE:([Expr1013]=CONVERT(varchar(17),[MyDB].[dbo].[MyTable].[MyPKey] as [D].[MyPKey],0)))
| |--Index Scan(OBJECT:([MyDB].[dbo].[MyTable].[IX_UpdateDate] AS [D]))
|--Compute Scalar(DEFINE:([Expr1012]=CONVERT_IMPLICIT(varchar(17),[tempdb].[dbo].[##MyTempTable].[MyPKey] as [S].[MyPKey],0)))
|--Clustered Index Scan(OBJECT:([tempdb].[dbo].[##MyTempTable] AS [S]))

denis_the_thief
Aged Yak Warrior

596 Posts

Posted - 2013-12-15 : 13:08:12
I not sure why so I'd appreciate any feedback, but here is what I think.

Your temp table is huge and SQL Server has to check each and everyone of these records for existense in the MyTable. Since there are so many rows to check it decides against the Index Seek and chooses the Hash Match. It needs to put MyPKey from every record from MyTable into the Hash table. Since it only needs column MyPKey in the Hash table, IX_UpdateDate will suffice since it has MyPKey in the leaf nodes. Wether it chooses IX_UpdateDate or PK_MyTable, it has to put the same number of values into the Hash Table. It must bring the entire Index from Disk to Memory first (at least whatever is not in Memory already). Since your table has 153 columns, it would be much quicker to bring IX_UpdateDate from Disk to Memory.
Go to Top of Page
   

- Advertisement -