Неверное поведение 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, и он ведет себя так же, как на SQL 2016.
Дин Савович

Ответы:

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;

Неправильный план

Обратите внимание, что в приведенном выше плане поиск удаляемых строк завершается раньше, чем ожидалось (из сканирования считываются только две строки). Защита Хэллоуина, как правило, корректно обрабатывается для In-Memory OLTP, просто кажется, что существует определенная проблема с комбинацией факторов, упомянутых выше.


Эта ошибка исправлена в SQL Server 2016 SP1 CU5 и SQL Server 2017 CU1 :

Пол Уайт 9
источник