gpt4 book ai didi

sql-server - NEWID() 和 PERSISTED 计算列的结果不一致

转载 作者:行者123 更新时间:2023-12-02 19:36:31 24 4
gpt4 key购买 nike

将 NEWID() 与持久计算列结合使用时,我得到了奇怪的结果。我是否使用了一些错误的功能?

创建列时不使用持久化,因此在选择列时计算值将返回正确的值。更新列 (col1) 也将返回正确的值。

DECLARE @test TABLE (
Col1 INT,
Contains2 AS CASE WHEN 2 IN (Col1) THEN 1 ELSE 0 END PERSISTED)

INSERT INTO @test (Col1) VALUES
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5))

SELECT * FROM @test
UPDATE @test SET Col1 = Col1*1
SELECT * FROM @test

/*
Col1 Contains2
2 0
2 0
0 1
4 0
3 0

Col1 Contains2
2 1
2 1
0 0
4 0
3 0
*/

最佳答案

显然,查询引擎为每行计算两次随机数。

第一次Col1 ,第二次为CASE持久化列的声明。

优化器不知道,或者在这种情况下不关心 NEWID是一个非确定性函数并调用它两次。

事实上,它甚至可能别无选择。您是否希望优化器在幕后创建临时表并填充其 Col1生成随机数的表达式的结果,然后读回该临时表并使用这些保存的中间结果来计算 CASE 的结果表达式,然后执行最后的INSERT ?在这种情况下,优化器计算表达式两次而不将中间结果写入磁盘会更便宜。在其他一些情况下(例如,当您没有 5 行,而是 50 亿行或额外的索引时),估计成本可能会有所不同,并且这种行为会发生变化。

我认为你对此无能为力。只要注意这种行为即可。始终将生成的随机数集显式保存到表中,然后根据它们执行进一步的计算。

我在 SQL Server 2008 和 2014 中重现了它。这是我在 SQL Server 2008 中得到的一个执行计划,但它并不是很有趣。 2014年的计划是一样的,只是没有Top运算符。

plan 2008

Constant Scan运算符输出 Union1009列表,用于 Compute Scalar之后。我想,这取决于 Constant Scan 的实现细节和/或 Compute Scalar运营商。

观察到的行为告诉我们 newid()这里每行被调用两次。

关于sql-server - NEWID() 和 PERSISTED 计算列的结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38120684/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com