Итак, я решил немного поэкспериментировать. Результат в наборе данных 1/10 размера ОП показал, что дополнительный выбор был выполнен лучше, чем левое соединение. Хотя я ожидаю, что левое объединение будет работать лучше в больших наборах данных. ОБНОВЛЕНИЕ: Я установил набор данных, такой как OP, и LEFT JOIN все еще не выполнил подвыбор, но он был очень близок.
Обеспечение наличия индексов в двух таблицах имеет решающее значение для скорости. Поэтому убедитесь, что ваши таблицы проиндексированы надлежащим образом.
/*
DROP TABLE Cookie
CREATE TABLE Cookie ([CookieID] [bigint] NOT NULL IDENTITY(1,1) PRIMARY KEY,Dummy bit)
DROP TABLE CookiePurpose
CREATE TABLE CookiePurpose (CookiePurposeID [bigint] NOT NULL IDENTITY(1,1) PRIMARY KEY, [CookieID] [bigint] NOT NULL)
CREATE NONCLUSTERED INDEX IX_CookiePurpose_CookieID ON dbo.CookiePurpose (CookieID)
SET NOCOUNT ON
DECLARE @CookieCounter BIGINT=(SELECT COUNT(CookieID) FROM Cookie)
WHILE @CookieCounter<500000 BEGIN INSERT INTO Cookie(Dummy) SELECT 1; SET @CookieCounter=@CookieCounter+1; END
DECLARE @CookiePurposeCounter BIGINT=(SELECT COUNT(CookieID) FROM CookiePurpose)
WHILE @CookiePurposeCounter<1000000 BEGIN INSERT INTO CookiePurpose(CookieID) SELECT Round(( ( 1000000000 - 1 - 1 ) * Rand() + 1 ), 0); SET @CookiePurposeCounter=@CookiePurposeCounter+1; END
*/
--EXCEPT: 300ms @ 1/10 data; 2917ms for full data
DECLARE @start DATETIME2,@end DATETIME2; SET @start=GETDATE()
DECLARE @KnownCookieIDs TABLE ([CookieID] [bigint] NOT NULL)
INSERT INTO @KnownCookieIDs
SELECT CookieID FROM CookiePurpose
EXCEPT
SELECT CookieID from Cookie
SET @end=GETDATE(); SELECT DATEDIFF(ms,@start,@end) AS [ms elapsed];
GO
--LEFT JOIN: 123ms @ 1/10 data; 1093ms for full data
DECLARE @start DATETIME2,@end DATETIME2; SET @start=GETDATE()
DECLARE @KnownCookieIDs TABLE ([CookieID] [bigint] NOT NULL)
INSERT INTO @KnownCookieIDs
SELECT c.CookieID
FROM Cookie c
LEFT JOIN CookiePurpose cp ON cp.CookieID=c.CookieID
WHERE cp.CookieID IS NULL
SET @end=GETDATE(); SELECT DATEDIFF(ms,@start,@end) AS [ms elapsed];
GO
--sub-select: 113 ms @ 1/10 data; 1046ms for full data
DECLARE @start DATETIME2,@end DATETIME2; SET @start=GETDATE()
DECLARE @KnownCookieIDs TABLE ([CookieID] [bigint] NOT NULL)
INSERT INTO @KnownCookieIDs
SELECT c.CookieID
FROM Cookie c
WHERe c.CookieID NOT IN (
SELECT CookieID FROM CookiePurpose
)
SET @end=GETDATE(); SELECT DATEDIFF(ms,@start,@end) AS [ms elapsed];
GO
--Delete: 767ms @ 1/10 data; 8450ms for full data
DECLARE @start DATETIME2,@end DATETIME2; SET @start=GETDATE()
DECLARE @KnownCookieIDs TABLE ([CookieID] [bigint] NOT NULL)
INSERT INTO @KnownCookieIDs
SELECT c.CookieID
FROM Cookie c
DELETE c
FROM @KnownCookieIDs c
INNER JOIN CookiePurpose cp ON cp.CookieID=c.CookieID
SET @end=GETDATE(); SELECT DATEDIFF(ms,@start,@end) AS [ms elapsed];
GO