SQL Server:非聚集索引不起作用

问题描述

我有一个包含主键的几列表格。我在表上创建了这个非聚集索引:

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 以及非聚集索引?

编辑:-

检查下面的屏幕截图。 if I dp.template_id= @TemplateId and dp.deleted = 0 in where 子句

enter image description here

如果我使用 ((@TemplateId = 0 or @TemplateId is null) or (dp.template_id= @TemplateId)) and dp.deleted = 0

enter image description here

解决方法

您是否尝试将@TemplateId 设置为外键?并删除template_id?我的意思是,当您可以根据一个值检查变量时,为什么还需要根据两个值来验证变量?

,

添加 OPTION(RECOMPLE) 查询提示。然后,SQL Server 可以使用 constant folding 在编译期间评估这些值,并从计划中消除不需要的谓词。

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

我认为测试这个索引是值得的,因为我认为这个索引对于两个查询来说都足够了,而且它更小。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...