[英]SQL Server : non-clustered index is not working
我有一个包含几列的表,包括一个主键。 我在表上创建了这个非聚集索引:
CREATE NONCLUSTERED INDEX [nci_wi_plan_239F85C77AF7B2990845ACFEE404C263]
ON dbo.[Plans] ([template_id] ASC, [deleted] ASC)
INCLUDE([HasWorkouts]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
GO
我在存储过程中执行此查询以从表中获取结果:
select
dp.id
,dp.HasWorkouts
from dbo.Plans dp
where dp.template_id= @TemplateId and dp.deleted = 0
--((@TemplateId = 0 or @TemplateId is null) or (dp.template_id= @TemplateId)) // not working if I use this line
在上面的查询中,非聚集索引仅在我使用一些 id 指示检查template_id
时才有效。 但有时我可能不需要检查dp.template_id
所以我在执行过程时将0 or null
设置为@TemplateId
。 有没有办法检查或跳过template_id
以及非聚集索引?
编辑:-
检查下面的屏幕截图。 如果我在 where 子句中dp.template_id= @TemplateId and dp.deleted = 0
如果我使用((@TemplateId = 0 or @TemplateId is null) or (dp.template_id= @TemplateId)) and dp.deleted = 0
您是否尝试将 @TemplateId 设置为外键? 并删除 template_id? 我的意思是,当您可以对照一个值检查一个变量时,为什么还需要对照两个值来验证它呢?
添加OPTION(RECOMPLE)
查询提示。 SQL 服务器然后可以在编译期间使用常量折叠来评估值并从计划中消除不需要的谓词。
OPTION(RECOMPLE)
的缺点是计划不会被重用,如果查询以高频率执行(即每秒多次),这可能是一个问题。 在这种情况下,您可以使用IF
构造来根据值执行不同的查询,而不是单个查询。 这将缓存两个计划。
如果您不想检查 template_id,请不要这样做:
IF @template_id IS NULL OR @template_id = 0
SELECT p.id dp.HasWorkouts
FROM dbo.Plans dp
WHERE dp.deleted = 0
ELSE
SELECT dp.id ,dp.HasWorkouts
FROM dbo.Plans dp
WHERE dp.template_id= @TemplateId and dp.deleted = 0
这实际上是两个查询,最好的覆盖索引是;
CREATE INDEX ix_template_id_is_deleted ON dbo.Plans(template_id, is_deleted)
INCLUDE (id, HasWorkouts)
和
CREATE INDEX ix_plans_is_deleted ON dbo.Plans(is_deleted)
INCLUDE (id, hasWorkouts)
另一种方法是通过这样的唯一查询:
SELECT dp.id, dp.HasWorkouts
FROM dbo.Plans dp
WHERE
(@template_id = 0 OR @template_id IS NULL OR dp.template_id= @TemplateId)
and dp.deleted = 0
OPTION (RECOMPILE)
但这需要在执行时重新编译查询以提高效率。
另一个可能值得尝试的索引如下:
CREATE INDEX ix_template_not_deleted ON dbo.Plans(template_id)
INCLUDE (id, HasWorkouts)
WHERE is_deleted = 0
我认为测试这个索引是值得的,因为我认为这个索引对于两个查询都足够了,而且它更小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.