Pan*_*tea 8 sql-server query t-sql sql-server-2016 query-performance
我有一个包含大量数据(近 1500 万)且结构如下的表。
create table test
(a int,--> /* There is a normal index on this column */
b int,
<other columns>)
Run Code Online (Sandbox Code Playgroud)
有一个从此表中进行选择的查询,其中 where 子句中的条件之一是:
where a!=1 or (a=1 and b!=0) /* The original condition */
Run Code Online (Sandbox Code Playgroud)
查询非常慢,我认为这种糟糕的性能大部分可能是由于逻辑运算符使用不当造成的。我已经改变了条件,如下所示:
where not (a=1 and b=0) /* The edited version*/
Run Code Online (Sandbox Code Playgroud)
并且性能发生了巨大的变化!我需要确定的是这两个条件完全相同,这样我就不会错过任何数据。我想知道您是否可以帮助我解决这个问题并告诉我您是否有更好的选择来治疗这种情况。
如果您知道任何有关逻辑运算的正确使用以及/顺序优化器处理它们的方式的文章,请分享链接。
提前致谢
And*_*y M 24
为了查明两个条件是否真正相等,您可以尝试为每个条件构建真值表并查看这两个表是否相同。
以下是构建真值表的方法。您有两个变量,a,它可能等于也可能不等于 1,以及b,它可能等于也可能不等于 0。编写并执行如下查询:
SELECT
a
, b
, [a!=1 or (a=1 and b!=0)] = CASE WHEN a!=1 or (a=1 and b!=0) THEN 'True' ELSE 'False' END
, [not (a=1 and b=0)] = CASE WHEN not (a=1 and b=0) THEN 'True' ELSE 'False' END
FROM
(
VALUES
( 1, 0)
, ( 1, 9999)
, (9999, 0)
, (9999, 9999)
) AS v (a, b)
;
Run Code Online (Sandbox Code Playgroud)
对于每个变量,指定与该变量进行比较的值,以便进行相应的比较 true 或 false(取决于它是=或!=),以及产生相反结果的另一个值。上面的值 9999 只是一个任意值,在与 比较时代表“非 1” a,在与 比较时代表“非 0” b。(我选择了与 1 或 0 完全不同的东西,以免使结果表太混乱。)
上述查询将返回以下输出:
| A | 乙 | a!=1 或 (a=1 且 b!=0) | 不是(a=1 且 b=0) |
|---|---|---|---|
| 1 | 0 | 错误的 | 错误的 |
| 1 | 9999 | 真的 | 真的 |
| 9999 | 0 | 真的 | 真的 |
| 9999 | 9999 | 真的 | 真的 |
正如您所看到的,对于相同的输入值,两个表达式给出相同的结果。
但请注意,上表仅包含使比较计算结果为True或False的值。这就是布尔代数中通常的情况。然而,在 SQL 世界中,布尔表达式可以计算出第三种状态,即Unknown又名Null。如果a可以为 null 并且确实为 null,则a=1(或a!=1就此而言)将计算为Unknown / Null。如果需要考虑可空性,那么我们的真值表应包含空值作为输入值。
以下是上述脚本的修改版本,其中两个变量都为空:
SELECT
a
, b
, [a!=1 or (a=1 and b!=0)] = CASE
WHEN a!=1 or (a=1 and b!=0) THEN 'True'
WHEN NOT (a!=1 or (a=1 and b!=0)) THEN 'False'
ELSE 'Unknown'
END
, [not (a=1 and b=0)] = CASE
WHEN not (a=1 and b=0) THEN 'True'
WHEN NOT (not (a=1 and b=0) ) THEN 'False'
ELSE 'Unknown'
END
FROM
(
VALUES
( 1, 0)
, ( 1, 9999)
, ( 1, NULL)
, (9999, 0)
, (9999, 9999)
, (9999, NULL)
, (NULL, 0)
, (NULL, 9999)
, (NULL, NULL)
) AS v (a, b)
;
Run Code Online (Sandbox Code Playgroud)
它给出以下输出:
| A | 乙 | a!=1 或 (a=1 且 b!=0) | 不是(a=1 且 b=0) |
|---|---|---|---|
| 1 | 0 | 错误的 | 错误的 |
| 1 | 9999 | 真的 | 真的 |
| 1 | 无效的 | 未知 | 未知 |
| 9999 | 0 | 真的 | 真的 |
| 9999 | 9999 | 真的 | 真的 |
| 9999 | 无效的 | 真的 | 真的 |
| 无效的 | 0 | 未知 | 未知 |
| 无效的 | 9999 | 未知 | 真的 |
| 无效的 | 无效的 | 未知 | 未知 |
上面突出显示的是两个条件不会产生相同结果的情况,即当a为 null 并且b是非 0 的非空值时。在这种情况下,第一个条件的结果未知,而另一个条件的结果为 true。
同样,这是假设a可以为 null,并且在该假设下,您的两个逻辑表达式不相等。但是,例如,如果 only bcan be null 且a不能为 null,那么您可以从上面的输出中看到相应行中的结果是相同的。
因此,您将根据所涉及变量的可空性找到答案。
更多阅读的几个链接:
| 归档时间: |
|
| 查看次数: |
2241 次 |
| 最近记录: |