为什么并行会影响我的查询是否成功?
Why does Parallelism affect if my query is successful?
本周遇到了一个 st运行ge 问题,其中查询第一次失败。它是存储过程的一部分,这是它失败的地方。 (我将字段更改为通用字段)
查询是
SELECT
p.Type,
CAST(c.Comment AS int) AS NumberOfComments
FROM Comments c
JOIN Pages p ON c.Id = p.Id
WHERE c.CommentNo = 5 AND p.Type IN ('AAA', 'BBB', 'CCC')
错误信息是
Conversion failed when converting the varchar value 'Test Text In here' to data type int.
使用通常的执行顺序,我希望 WHERE 在 SELECT CAST 之前执行,但在这种情况下并没有发生。在对评论 table 进行聚簇索引扫描后,有一个计算标量在其中进行了转换,然后对页面 Table.
进行了哈希匹配
评论字段不仅用于数字,而且这些特定类型的所有评论始终都是数字。我们通过使用 TRY_CAST 而不是 CAST 来修复它,但我也注意到查询本身已经并行。
当我添加 OPTION (MAXDOP 1) 然后查询 运行 成功。除了并行性之外,执行计划是相同的,因此它使用了类似的计划。
所以我想我的问题是为什么并行会导致此查询失败?
SQL 是一种查询语言,与过程语言没有任何关系。
在过程语言中,您可以通过对每个部分的代码片段进行排序来控制每条指令的顺序。这就是所谓的“如何”代码......
在查询语言中,您只指定“what”代码,而不是 how,查询被翻译成不同的指令序列(how 代码)来执行您的请求,然后根据成本,最后优化器选择将要执行的最佳一个。
有时,由于查询、会话执行参数、数据值分布的细微差异,代码的更改方式...
因此,您绝不能假定查询将以相同的方式执行。您需要通过消除误解的逻辑来保护您的查询...
原因是 c.Comment
的值不是数字。所以,转换失败。 即使在 WHERE
子句中过滤掉了行,也会发生这种情况。
此外,子查询、CTE 和视图也无济于事。为什么不?因为 SQL 优化器可以重新安排处理。在这种情况下,它可以决定在过滤行之前将转换“推”得更靠近数据源。
Microsoft 不 认为这是一个错误(事实上,这是一个“优化功能”),尽管我认为这是一个错误。但是有一种非常简单的方法可以使用 TRY_CAST()
:
来修复它
SELECT p.Type,
TRY_CAST(c.Comment AS int) AS NumberOfComments
FROM Comments c JOIN
Pages p
ON c.Id = p.Id
WHERE c.CommentNo = 5 AND p.Type IN ('AAA', 'BBB', 'CCC');
本周遇到了一个 st运行ge 问题,其中查询第一次失败。它是存储过程的一部分,这是它失败的地方。 (我将字段更改为通用字段)
查询是
SELECT
p.Type,
CAST(c.Comment AS int) AS NumberOfComments
FROM Comments c
JOIN Pages p ON c.Id = p.Id
WHERE c.CommentNo = 5 AND p.Type IN ('AAA', 'BBB', 'CCC')
错误信息是
Conversion failed when converting the varchar value 'Test Text In here' to data type int.
使用通常的执行顺序,我希望 WHERE 在 SELECT CAST 之前执行,但在这种情况下并没有发生。在对评论 table 进行聚簇索引扫描后,有一个计算标量在其中进行了转换,然后对页面 Table.
进行了哈希匹配评论字段不仅用于数字,而且这些特定类型的所有评论始终都是数字。我们通过使用 TRY_CAST 而不是 CAST 来修复它,但我也注意到查询本身已经并行。
当我添加 OPTION (MAXDOP 1) 然后查询 运行 成功。除了并行性之外,执行计划是相同的,因此它使用了类似的计划。
所以我想我的问题是为什么并行会导致此查询失败?
SQL 是一种查询语言,与过程语言没有任何关系。 在过程语言中,您可以通过对每个部分的代码片段进行排序来控制每条指令的顺序。这就是所谓的“如何”代码...... 在查询语言中,您只指定“what”代码,而不是 how,查询被翻译成不同的指令序列(how 代码)来执行您的请求,然后根据成本,最后优化器选择将要执行的最佳一个。
有时,由于查询、会话执行参数、数据值分布的细微差异,代码的更改方式...
因此,您绝不能假定查询将以相同的方式执行。您需要通过消除误解的逻辑来保护您的查询...
原因是 c.Comment
的值不是数字。所以,转换失败。 即使在 WHERE
子句中过滤掉了行,也会发生这种情况。
此外,子查询、CTE 和视图也无济于事。为什么不?因为 SQL 优化器可以重新安排处理。在这种情况下,它可以决定在过滤行之前将转换“推”得更靠近数据源。
Microsoft 不 认为这是一个错误(事实上,这是一个“优化功能”),尽管我认为这是一个错误。但是有一种非常简单的方法可以使用 TRY_CAST()
:
SELECT p.Type,
TRY_CAST(c.Comment AS int) AS NumberOfComments
FROM Comments c JOIN
Pages p
ON c.Id = p.Id
WHERE c.CommentNo = 5 AND p.Type IN ('AAA', 'BBB', 'CCC');