SQL Server - 使用NOT EXISTS的替代方法

时间:2016-01-14 06:54:16

标签: sql-server performance tsql not-exists query-tuning

我有一个包含EntityID列的大约200,000条记录的列表,我将其加载到临时表变量中。

如果dbo.EntityRows表中不存在Temp表中的EntityID,我想插入Temp表变量中的任何记录。 dbo.EntityRows表包含大约800,000条记录。

与dbo.EntityRows表有大约500,000条记录的情况相比,该过程非常缓慢。

我的第一个猜测是因为NOT EXISTS子句,Temp变量中的每一行都必须扫描dbo.EntityRows表的整个800k行以确定它是否存在。

问题:是否有其他方法可以在不使用NOT EXISTS的情况下运行此比较检查,这会产生巨大的成本,并且只会随着dbo.EntityRows继续增长而变得更糟?

编辑:感谢评论。这是查询(我在IF NOT EXISTS检查之后省略了部分。之后,如果不是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

3 个答案:

答案 0 :(得分: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&#39;说

答案 1 :(得分: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

如果您想了解更多信息,请发表评论。

答案 2 :(得分:0)

嗯,答案很基本。 @Felix和@TT有正确的建议。谢谢!

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

public Token analyzeToken(String regex, String string) {
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(string); // match the string, not the token!
            if(m.matches()) {
               // ...
            }

因此它现在可以使用索引快速处理NOT EXISTS部分,而不是扫描整个dbo.entity表。它再次快速移动。