首页 > 解决方案 > SQL Server 查询连接优化

问题描述

我在网上找了答案,但找不到明确的答案。例如,您有 2 个连接子句:

1.

JOIN T2 ON T1.[ID] = T2.[ID]

2.

JOIN T2 ON T1.[ID] = REPLACE(T2.[ID],'A', '')

现在第二个由于连接子句上的功能而表现更差。这样做的确切原因是什么?

例如,如果这段代码在一个存储过程中,那么优化它的最佳方法是什么?要删除替换功能并将其添加到表级别,以便所有这些都在任何连接之前完成?

任何建议或更多信息的链接都会很棒。谢谢

标签: sqlsql-serverjoinoptimization

解决方案


在您的第二个示例中,您尝试在 T2 中查找记录 - 但不是 T1.ID 值,而是将函数应用于 T2.ID - REPLACE(T2.[ID],'A', '')

如果您在 T2.ID 上有一个索引 - 充其量它会扫描索引而不是寻找它 - 从而导致性能差异。

这是更难解释的地方 - 索引存储为表中 T2.ID 的值的 b+树。索引理解该字段并可以按它搜索/排序,但它不理解应用于它的任何逻辑。

它不知道是否REPLACE('A123','A', '') = 123- 没有对索引中的值执行函数并检查结果相等。

AAA123 也将相等,1A23、12A3、123A 等,实际上匹配的组合数量无穷无尽 - 但它可以确定单个索引条目是否匹配的唯一方法是通过运行该值函数,然后检查相等性。

如果它只能在通过函数运行索引值时弄清楚这一点——它只有在对索引中的每个条目都这样做时才能正确回答查询——例如,对每个条目进行索引扫描,传递给函数和输出被检查。

正如 Jeroen 提到的,该术语是 SARGable 或 SARGability, earch ument SARG尽管ABLE我个人更喜欢将其解释为Seek ARGument ,ABLE因为它更接近于查询计划运算符。

应该注意的是,这个概念与它是一个连接无关,SQL 中的任何谓词都有这个限制 - 带有 where 谓词的单个表查询可能有同样的问题。

这个问题可以避免吗?它可以但仅在某些情况下,您可以反转操作。

考虑一个带有 ID 列的表,我可以构造一个谓词,如下所示: WHERE ID * 2 = @paramValue

SQL Server 知道乘以 2 的 ID 条目是否是传入值的唯一方法是处理每个条目,将其加倍并检查。这又是索引扫描场景。

在这种情况下,我们可以重写它: WHERE ID = @paramValue / 2.0

现在 SQL Server 将执行一次数学运算,将传入的值相除,然后它可以以可搜索的方式检查索引。编写的 SQL 的差异在陈述问题方面看起来可能微不足道,但对数据库如何解析谓词产生了非常大的差异。


推荐阅读