【发布时间】:2020-12-10 10:42:03
【问题描述】:
我有一个包含 3 个字段的表,我创建了一个复合索引。我需要它来检查记录是否存在。
这是我的桌子
tblGamePlayLog
UserId (PK)
LogId (PK)
...
...
ProviderId
ResellerId
GameId
...
...
-- ProviderId, ResellerId and GameId is indexed (composite index)
我有这样的存储过程
CREATE PROCEDURE [AS.uspProviderResellerGame_IsDeletable]
(
@ProviderId INT = -1, --Use -1 to ignore this field
@ResellerId INT = -1, --Use -1 to ignore this field
@GameId INT = 1, --Use -1 to ignore this field
@IsDeletable BIT = 0 OUT
)
AS
BEGIN
SET @IsDeletable = 1;
...
...
...
ELSE IF (EXISTS(SELECT TOP 1 1 FROM [tblGamePlayLog] WHERE ((@ProviderId = -1) OR ([ProviderId] = @ProviderId)) AND ((@ResellerId = -1) OR ([ResellerId] = @ResellerId)) AND ((@GameId = -1) OR ([GameId] = @GameId)))) SET @IsDeletable = 0;
END;
此存储过程允许调用函数传递 -1 以忽略对特定字段的检查。但是,它会导致查询显着变慢(由于日志包含 100 万条记录,因此速度会慢 1000 倍)。
如果我去掉 -1 检查,速度会显着提高。
...
...
...
ELSE IF (EXISTS(SELECT TOP 1 1 FROM [tblGamePlayLog] WHERE ([ProviderId] = @ProviderId) AND ([ResellerId] = @ResellerId) AND ([GameId] = @GameId))) SET @IsDeletable = 0;
我怀疑,但添加 -1 检查,SQL 不使用索引检查。我的问题是,如何在 WHERE 子句中允许 -1 检查但保留索引检查。
【问题讨论】:
-
option(recompile)可能会有所帮助。 -
我同意@GMB 的观点,即
OPTION (RECOMPILE)查询提示将成为解决方案的一部分。但是您仍然需要考虑索引需要有谓词的最左边的列才能有效使用。您需要多个索引才能对您的用例进行高效查询。 -
我尝试在存储过程中使用
WITH RECOMPILE。还是很慢…… -
我也使用了GMB推荐的
OPTION (RECOMPILE),它提高了速度,但仍然很慢... :(
标签: sql sql-server stored-procedures query-optimization where-clause