sql - 了解 SQL Server 索引
问题描述
对不起,很长的帖子。我们有一个每 10 分钟左右运行一次的数据提取,用于将数据从源表传输到我们的数据仓库。
代码看起来像这样:
SELECT
Column1,
Column2,
Column3,
Column4
FROM
dbo.Table
WHERE
LastModifiedDate > @LastRun
OR CreatedDate > @LastRun
OR CancelledDate > @LastRun
OR DeletedDate > @LastRun
该@LastRun
参数通过 SSIS 包传递,并包含我们运行的最后一个日期时间(因此我们只带回我们需要的内容)。
尽管每次只返回 50-70 行,但此代码在源系统上运行非常缓慢。
我们有 2 个技术团队就性能问题进行联络。一个团队建议表上没有索引来支持此提取查询,并且向日期列添加索引将使查询运行更顺畅。
另一个团队说代码需要重新编写,因为“将索引添加到日期列会增加问题,因为它是一个过于生硬的工具”。他们还建议为我们创建一个索引视图来从中提取数据,而不是转到实际的表本身。
对此最好的方法是什么?只是想真正获得意见,因为我的印象是,如果用于过滤的列根本没有索引,那么代码的编写方式并不重要?
欣赏任何想法!
解决方案
OR
s 对于索引来说是非常糟糕的逻辑。如果每列都有单独的索引,则可以将其转换为union all
:
select . . .
from t
where LastModifiedDate > @LastRun
union all
select . ..
from t
where CreatedDate > @LastRun and
not (LastModifiedDate > @LastRun)
union all
select . ..
from t
where CancelledDate > @LastRun and
not (LastModifiedDate > @LastRun and CreatedDate > @LastRun )
union all
select . ..
from t
where DeletedDate > @LastRun and
not (LastModifiedDate > @LastRun and CreatedDate > @LastRun and CancelledDate > @LastRun);
注意:如果列可以为空,逻辑会稍微复杂一些。
这种方法也很麻烦,因为需要重复查询四次,并且对所有四列都有索引。如果 SQL Server ——以其无限的智慧——决定不为一个子查询使用索引,你就会陷入性能更差的解决方案中。
另一种方法是在计算列上使用索引:
alter table t add most_recent_date as
(case when LastModifiedDate >= CreatedDate and LastModifiedDate >= CancelledDate and LastModifiedDate >= DeletedDate then LastModifiedDate
when CreatedDate >= CancelledDate and CreatedDate >= DeletedDate then CreatedDate
when CancelledDate >= DeletedDate then CancelledDate
else DeletedDate
end) persisted;
create index idx_most_recent_date on t(most_recent_date);
请注意,如果任何日期都可以,则计算列逻辑会稍微复杂一些NULL
。如果这些设置在触发器中,则只需修改触发器以使最新日期保持最新可能会更简单。
然后,您可以将查询表述为:
where most_recent_date > @LastRun
推荐阅读
- c# - 如何在 UWP 应用中检测 VoIP 呼叫事件
- neo4j - 如何获取一个节点的所有子节点
- javascript - 我们可以用 ctrl+enter 替换“textarea” shift+enter 行为吗?
- excel - 从网站列表中抓取数据
- spring - 如何使用 Spring 在 mongodb 文档的嵌套数组中添加 json?
- reactjs - 如何在线在 Sharepoint 中托管示例 React 应用程序?
- office-js - Office-addin 身份验证、审批流程
- raspberry-pi4 - 跳过获取配置文件
- python - 在 python 中导入自定义包
- image - 如何在 Dart Image.network 中获取原始图像大小?