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

如何解决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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?