2017-07-25 48 views
0

我想檢查我的數據庫表的同義詞表記錄。使用同義詞SQL Server查詢性能問題

下面的語句工作正常,我,但我想擺脫插入和臨時表:

IF OBJECT_ID('tempdb..#tmp_table') IS NOT NULL 
    DROP TABLE #tmp_table 

SELECT 
    id 
INTO 
    #tmp_table 
FROM 
    synonyms_table WITH (nolock) 
WHERE 
    created_date BETWEEN GETDATE() - 4 AND GETDATE() - 1 

SELECT id 
FROM #tmp_table tmp  
LEFT JOIN main_table main WITH (NOLOCK) ON tmp.id COLLATE SQL_Latin1_General_CP1_CI_AS = main.id 
WHERE main.id IS NULL 

的問題是,這兩個表是巨大的,如果我要使用左側加入或不存在的,這將是非常緩慢:

SELECT id 
FROM synonyms_table sy WITH (NOLOCK) 
LEFT JOIN main_table main WITH (NOLOCK) ON sy.id COLLATE SQL_Latin1_General_CP1_CI_AS = main.id 
WHERE sy.created_date BETWEEN GETDATE() - 4 AND GETDATE() - 1 
    AND main.id IS NULL 

也許有人知道這裏對我來說是很好的解決方案:)

+1

爲什麼你想擺脫臨時表,如果這工作正常? –

+1

我會停止使用'getdate() - 4'並明確地使用'DateAdd()'來明確並防止以後發生錯誤。爲什麼不直接加入到synonyms義表中? – scsimon

回答

0

你可以嘗試這樣的事情,銘記優化器可能決定運行追溯到非高性能版本的執行計劃:

你的開銷
WITH Base AS (
    SELECT 
     id COLLATE DATABASE_DEFAULT AS id 
    FROM 
     synonyms_table WITH (NOLOCK) 
    WHERE 
     created_date BETWEEN DATEADD(DAY, -4, GETDATE()) AND DATEADD(DAY, -1, GETDATE())) 
SELECT 
    id 
FROM 
    Base b 
    LEFT JOIN main_table main WITH (NOLOCK) ON b.id = main.id 
WHERE 
    main.id IS NULL; 

一種是整理,所以在公共表表達式我預先整理數據。

1

如果您的目標是從同義詞表中獲取主表中不存在的記錄,則應該使用NOT EXISTS。它應該表現得更好,但是直到你嘗試之後你纔會知道。

SELECT Id 
FROM synonyms_table s 
WHERE s.created_date BETWEEN DATEADD(DAY, -4, GETDATE()) 
    AND DATEADD(DAY, -1, GETDATE())) 
AND NOT EXISTS 
(
    SELECT * FROM main_table m 
    WHERE m.Id = s.Id COLLATE DATABASE_DEFAULT 
) 

但是,如果#temp表解決方案工作得更好,我肯定會保留它。事實上,我會建議兩個可以進一步提高性能的改進。

1)而不是使用校勘加入(這是昂貴的),你可以通過添加COLLATE創建正確的排序規則,臨時表的SELECT INTO

SELECT id COLLATE SQL_Latin1_General_CP1_CI_AS AS Id 
INTO #tmp_table 
FROM synonyms_table 

2)創建後創建的臨時表的聚集索引並在加入之前

CREATE CLUSTERED INDEX ix_tmp_table ON #tmp_table (Id)