【问题标题】:where isnull (DateX, DateY) >= getdate()其中 isnull (DateX, DateY) >= getdate()
【发布时间】:2017-02-23 01:54:18
【问题描述】:

谁能告诉我提高以下 SQL 性能的方法?

select A, B from T_XXX
where isnull(DateX, DateY) >= getdate()
  • 在 DateX 或 DateY 上都没有索引。
  • 目前没有关于 DateX 中 NULL 和非 NULL 值的比例的信息。

(添加评论) 感谢您的回复!如果以“无索引”为前提,SQL 是否还有改进的余地?

【问题讨论】:

  • No index on either DateX or DateY. 不是创建它们的答案吗?
  • 您可以创建一个使用isnull(DateX, DateY) 作为其值的计算列。
  • @artm 谢谢!我添加了评论。很抱歉有歧义。
  • @DavidG 感谢您的建议!在使用索引计算计算列的空间以及使用它们更新表所需的额外时间之后,我将与我们的 DBA 协商。

标签: sql sql-server tsql sql-tuning


【解决方案1】:

提高性能的最简单方法是在ISNULL(DateX, DateY) 上创建索引。在DateX 和/或DateY 上拥有单独的索引可能无济于事,因为ISNULL 函数可能会否定使用索引的能力。

如果您确实在任一列上都有索引,则可以将子句重写为

WHERE DateX >= GETDATE() OR (DateX IS NULL AND DateY >= GETDATE())

可以利用任一索引。

SQL Server 可能在内部将ISNULL 转换为可以使用索引的等效子句,但您必须尝试两种方式,看看是否有性能改进可以确定, '

如果以“无索引”为前提,SQL 是否还有改进空间?

不直接。 SQL 是声明性的,这意味着你给它一个你想要什么的想法,它会提出它认为是收集数据的最佳计划。在这种情况下,仅通过更改 SQL 就无法改变性能。

【讨论】:

  • 是否有直接的方法为ISNULL(DateX, DateY) 创建索引?您是指带索引的计算列吗?
  • D 斯坦利,非常感谢您的回答!虽然考虑到 ETL 持续时间和磁盘空间,我们的 DBA 不会轻易允许添加索引,但如果没有其他方法,我会与他们协商。
  • @yobioo 添加索引时,选择性能和插入/更新性能之间肯定存在权衡。这可能不是 DBA 愿意牺牲的东西,除非您能证明总体节省的成本是显着的。
  • @Eric, @D Stanley 似乎 SQL Server 需要一个计算列来执行此操作,而 Oracle/Postgresql 允许对表达式进行索引。
  • @Eric 看起来我错了,你确实需要一个计算列 - 我很惊讶它在 SQL Server 中不起作用。
【解决方案2】:

您也许可以通过 UNION 来改进这一点:

select A, B from T_XXX
where DateX >= getdate()

UNION

select A, B from T_XXX
where DateY >= getdate() and DateX IS NULL

但您仍然可能需要索引才能充分利用这一点。

【讨论】:

  • 实际上,如果没有索引,这可能是 两次 表扫描,除非引擎足够聪明,可以在扫描时适当地存储结果。
  • @Joel 谢谢你的技巧!我什至没有想到。在我当前的环境中,它比原来的环境花费了更多的时间,这可能是因为 D Stanley 指出的和/或重复数据删除的成本。
  • 我将在每个表上为非空数据添加过滤索引。这将使索引小于未过滤的对应索引,并且只有一次读取。
  • @Horaciux 感谢您的建议!实际上,我对过滤索引并不熟悉,并且刚刚了解它。它似乎对我们的情况有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多