SQL Server 2016具有内存优化表的不正确行为


13

请查看以下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

在我看来,这像是个小虫,对您来说,看起来是否如此?


是的,这是一个错误。测试了SQL 2017年CTP 2.1和因为它在2016年的SQL它的表现一样
迪恩萨沃维奇

Answers:


12

是的,它是一个错误,似乎只通过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正确处理万圣节保护,似乎是上述因素综合导致的一个特定问题。


此错误已在SQL Server 2016 SP1 CU5SQL Server 2017 CU1中修复

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.