Comportamento incorreto do SQL Server 2016 com tabelas com otimização de memória

13

Por favor, dê uma olhada na seguinte consulta 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

Ao executá-lo no SQL Server 2014 (12.0.4100.1 X64) UPDATE, a consulta é executada conforme o esperado e o seguinte resultado válido é retornado:

source_col | target_col
----------------------
10 -1
0 -1

No entanto, ao executar no SQL Server 2016 (13.0.4001.0 X64), nem todas as linhas são atualizadas e o seguinte é retornado:

source_col | target_col
----------------------
10 -1
0 0 0

Isso parece um bug para mim, parece assim para você?

Dmitry Savchenko
fonte
Sim, isso é um bug. Testou-o no SQL 2017 CTP 2.1 e se comporta da mesma forma que no SQL 2016.
Dean Savović

Respostas:

12

Sim, é um bug que parece afetar apenas as variáveis ​​da tabela, com um método de acesso ao índice bw-tree e uma associação automática não correlacionada.

Reprodução simplificada usando 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;

Plano defeituoso

Observe no plano acima que a pesquisa de linhas a serem excluídas termina antes do esperado (apenas duas linhas são lidas na varredura). A proteção de Halloween geralmente é tratada corretamente no OLTP na memória, apenas parece haver um problema específico com a combinação dos fatores mencionados acima.


Esse bug foi corrigido no SQL Server 2016 SP1 CU5 e no SQL Server 2017 CU1 :

Paul White 9
fonte