Самый быстрый способ объединения двух таблиц в разных строках? - PullRequest
0 голосов
/ 26 июня 2018

У меня есть две таблицы с одинаковым именем столбца: CookieID (bigint)

  1. таблица (Cookies) имеет 5 миллионов записей

Я хочу создать новую таблицу, в которой есть только CookieID из # 1, которых нет в # 2.

Следующий подход занял более 20 минут.

CREATE TABLE #KnownCookieIDs

(
    [CookieID] [bigint] NOT NULL
)

INSERT INTO 
#KnownCookieIDs
SELECT CookieID FROM CookiePurpose
EXCEPT
SELECT CookieID from Cookies

Есть ли более быстрый способ достичь этого?

Обновление

Я тестировал базу данных Azure с планом уровня S0, который имеет 10 DTU. Я подумал, что длительное время запроса было из-за этого, поэтому я сейчас нахожусь в процессе экспорта БД на мою локальную машину и попробую ваши предложения оттуда.

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Итак, я решил немного поэкспериментировать. Результат в наборе данных 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
0 голосов
/ 26 июня 2018

Этот запрос должен работать быстрее:

CREATE TABLE #KnownCookieIDs

(
    [CookieID] [bigint] NOT NULL
)

INSERT INTO 
    #KnownCookieIDs
SELECT 
    c.CookieID 
FROM 
    Cookie c
    LEFT JOIN CookiePurpose cp ON c.CookieID = cp.CookieID
WHERE
    cp.CookieID IS NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...