2016-01-14 67 views
0

我有一個包含EntityID列的約200,000條記錄的列表,我將其加載到一個臨時表變量中。SQL Server - 使用NOT EXISTS的替代方案

如果Temp表中的EntityID不存在於dbo.EntityRows表中,我想從Temp表變量中插入任何記錄。 dbo.EntityRows表包含大約800,000條記錄。

與dbo.EntityRows表具有大約500,000條記錄相比,此過程非常緩慢。

我的第一個猜測是因爲NOT EXISTS子句,來自Temp變量的每一行都必須掃描dbo.EntityRows表的整個800k行以確定它是否存在。

問題:是否有其他方法可以在不使用NOT EXISTS的情況下運行此比較檢查,這會產生沉重的成本,並且只會隨着dbo.EntityRows的持續增長而變得更糟?

編輯:欣賞意見。這裏是查詢(我在IF NOT EXISTS檢查後省略了部分,之後如果不存在,我插入4個表格中)。

declare @EntityCount int, @Counter int, @ExistsCounter int, @AddedCounter int 
declare @LogID int 
declare @YdataInsertedEntityID int, @YdataSearchParametersID int 
declare @CurrentEntityID int 
declare @CurrentName nvarchar(80) 
declare @CurrentSearchParametersID int, @CurrentSearchParametersIDAlreadyDone int 
declare @Entities table 
(
    Id int identity, 
    EntityID int, 
    NameID nvarchar(80), 
    SearchParametersID int 
) 

insert into @Entities 
select EntityID, NameID, SearchParametersID from YdataArvixe.dbo.Entity  order by entityid; 


set @EntityCount = (select count(*) from @Entities); 
set @Counter = 1; 
set @LogID = null; 
set @ExistsCounter = 0; 
set @AddedCounter = 0; 
set @CurrentSearchParametersIDAlreadyDone = -1; 

While (@EntityCount >= @Counter) 
begin 
    set @CurrentEntityID = (select EntityID from @Entities 
           where id = @Counter) 

    set @CurrentName = (select nameid from @Entities 
            where id = @Counter); 

    set @CurrentSearchParametersID = (select SearchParametersID from @Entities 
              where id = @Counter) 

    if not exists (select 1 from ydata.dbo.entity 
        where NameID = @CurrentName) 
    begin 
     -- I insert into 4 tables IF NOT EXISTS = true 
    end 
+4

通常,['NOT EXISTS'是最快的方法](http://sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join)。您可能需要添加索引以加快查詢速度。 –

+1

你可以發佈您的查詢。 –

+1

你可以用'temporary-table'替換'table-variable'嗎?根據您的實例設置,服務器可以選擇使用並行計劃並優化查詢。 「表變量」不能成爲這種計劃的一部分,因爲服務器「認爲」它只有一行。 – gotqn

回答

0

那麼,答案是非常基本的。 @Felix和@TT有正確的建議。謝謝!

我在ydata.dbo.entity中的NameID字段上放置了非聚集索引。

if not exists (select 1 from ydata.dbo.entity 
        where NameID = @CurrentName) 

因此,它現在可以使用索引快速處理NOT EXISTS部分,而不是掃描整個dbo.entity表。它正在快速移動。

0

我不知道,但有以下幾種方式,我們怎麼能檢查

(SELECT COUNT(er.EntityID) FROM dbo.EntityRows er WHERE er.EntityID = EntityID) <> 0 

(SELECT er.EntityID FROM dbo.EntityRows er WHERE er.EntityID = EntityID) IS NOT NULL 

EntityID NOT EXISTS (SELECT er.EntityID FROM dbo.EntityRows er) 

EntityID NOT IN (SELECT er.EntityID FROM dbo.EntityRows er) 

但按我的信念讓數將給予良好的性能。 同樣索引將有助於提高性能,因爲'Felix Pamittan'說

+2

獲得計數可能會給你**非常糟糕的**表現 - 因爲它需要越過**所有行**以確定計數 - 當你真的只想知道給定的值是否存在或不存在......「NOT EXISTS」將會一旦找到匹配值就會停止**循環...... –

0

正如@gotqn所說,使用臨時表開始。表格填充後,在EntityID上創建一個索引。如果EntityRows中的EntityID沒有索引,請創建一個。

我做這樣的事情很多,我一般採用以下模式:

INSERT INTO EntityRows (
    EntityId, ... 
) 

SELECT T.EntityId, ... 
FROM #tempTable T 
LEFT JOIN EntityRows E 
ON T.EntityID = E.EntityID 
WHERE E.EntityID IS NULL 

請發表評論,如果您想進一步的信息。

+0

我應該使用臨時表,因爲涉及的行並不小。我會在臨時表上添加一個索引。將發佈結果,謝謝! – nanonerd