Sql-Server
記憶體優化表的 SQL Server 2016 行為不正確
請查看以下 SQL 查詢:
CREATE TYPE dbo.IN_MEMORY_TABLE_TYPE AS TABLE ( source_col INT NULL, target_col INT not NULL INDEX ix_InMemoryTable NONCLUSTERED (target_col) ) WITH (MEMORY_OPTIMIZED = ON) GO DECLARE @t dbo.IN_MEMORY_TABLE_TYPE INSERT @t ( source_col, target_col ) VALUES (10, 0), (0, 0) UPDATE r1 SET target_col = -1 FROM @t r1 WHERE EXISTS ( SELECT * FROM @t r2 WHERE r2.source_col > 0 ) SELECT * FROM @t GO DROP TYPE dbo.IN_MEMORY_TABLE_TYPE
在 SQL Server 2014 (12.0.4100.1 X64) 上
UPDATE
執行時,查詢按預期執行,並返回以下有效結果:source_col | target_col ---------------------- 10 | -1 0 | -1
但是,在 SQL Server 2016 (13.0.4001.0 X64) 上執行時,並非所有行都得到更新,並返回以下內容:
source_col | target_col ---------------------- 10 | -1 0 | 0
這在我看來像一個錯誤,在你看來是這樣嗎?
是的,這是一個錯誤,它似乎只影響表變數,具有 bw-tree 索引訪問方法和不相關的自連接。
使用以下簡化再現
DELETE
:CREATE TYPE dbo.IN_MEMORY_TABLE_TYPE AS TABLE ( col integer NOT NULL INDEX i NONCLUSTERED (col) ) WITH (MEMORY_OPTIMIZED = ON); GO DECLARE @T AS dbo.IN_MEMORY_TABLE_TYPE; INSERT @T (col) VALUES (1), (2), (3), (4), (5); DELETE T FROM @T AS T WHERE EXISTS ( SELECT 1 FROM @T AS T2 WHERE T2.col = 1 -- Vary this number 1-5 ); SELECT T.col FROM @T AS T; GO DROP TYPE dbo.IN_MEMORY_TABLE_TYPE;
請注意,在上面的計劃中,要刪除的行的搜尋比預期的要早終止(從掃描中只讀取了兩行)。對於記憶體中 OLTP,萬聖節保護通常得到了正確處理,只是上述因素的組合似乎存在一個特定問題。