I am trying to keep track of whether I need to update certain tables. I have an Events table which I am wanting to monitor for changes and have another table, called DictionaryRefresh, which keeps track of the changes made to that table. If the Events table gets edited, it's edittime will be saved and fall later than the last refresh time of the DictionaryRefresh table hence indicating the need to refresh. In addition, if new rows are added to the Events table, then there also needs to be associated new entries in the DictionaryRefresh table - hence the LEFT JOIN.
Here are the table structures
CREATE TABLE [dbo].[DictionaryRefresh]
(
[LookupKey] [varchar](31) NOT NULL,
[LookupValue] [varchar](255) NOT NULL,
[RecordNumber] [int] NULL,
[RefreshTime] [datetime] NULL,
[EventKey] [varchar](31) NULL,
[MappedLookupKey] [varchar](31) NULL
) ON [PRIMARY]
The indexes are (following the DBEngine Tuning Advisor)
CREATE NONCLUSTERED INDEX [idx_DictionaryRefresh2146B4EB]
ON [dbo].[Ifx_DictionaryRefresh] ([LookupKey] ASC)
CREATE NONCLUSTERED INDEX [idx_DictionaryRefresh51EC6492]
ON [dbo].[Ifx_DictionaryRefresh] ([MappedLookupKey] ASC, [RefreshTime] ASC, [RecordNumber] ASC, [EventKey] ASC)
CREATE NONCLUSTERED INDEX [idx_DictionaryRefreshFCDAD7FA]
ON [dbo].[Ifx_DictionaryRefresh] ([LookupValue] ASC)
The Events table is as follows:
CREATE TABLE [dbo].[Events](
[RecordNumber] [int] NOT NULL,
...
[EventKey] [varchar](31) NOT NULL,
...
[EditTime] [datetime] NULL,
...
PRIMARY KEY CLUSTERED([RecordNumber] ASC)
CREATE NONCLUSTERED INDEX [idxEvents299ADAC8]
ON [dbo].[Events]([EditTime] ASC)
CREATE NONCLUSTERED INDEX [idxEvents5B151A5E]
ON [dbo].[Events]([EventKey] ASC)
Now the SQL I am running is as follows - it is taking almost a minute to return. If I execute the subquery only it returns pretty much immediately.
IF EXISTS (
SELECT 1
FROM (
SELECT
e.EventKey AS DictionaryKey
,ISNULL(e.EditTime, '1 Jan 1900 01:00') AS EditTime
,e.RecordNumber AS DictionaryRecordNumber
FROM Events e) d
LEFT JOIN DictionaryRefresh r ON r.RecordNumber = DictionaryRecordNumber
AND r.EventKey = DictionaryKey
AND r.MappedLookupKey = 'M18E2I501'
WHERE r.RefreshTime < d.EditTime
OR r.RecordNumber IS NULL)
BEGIN
PRINT 'TRUE'
END
There are approx 130K rows in the DictionaryRefresh
table, and approx 8K rows in the Events
table
When the DictionaryRefresh
table is empty or small it is very fast but slows down as the number of rows in DictionaryRefresh increases especially if none match the criteria.
Here is the execution plan.
and the salient stats (the index seek taking 94% of the cost - the number of rows accessed is effectively the square of the number of rows in the Events table) ...
I have tried replacing the
IF EXISTS
with
IF (SELECT COUNT ...) <> 0
as well as
IF (SELECT TOP 1 1 ...) = 1
but none seemed any faster.
I would obviously appreciate any suggestions you might have.
Thanks in advance.
S