Comportement incorrect de SQL Server 2016 avec des tables optimisées en mémoire


13

Veuillez consulter la requête SQL suivante:

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

Lors de son exécution sur SQL Server 2014 (12.0.4100.1 X64), UPDATEla requête s'exécute comme prévu et le résultat valide suivant est renvoyé:

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

Cependant, lors de l'exécution sur SQL Server 2016 (13.0.4001.0 X64), toutes les lignes ne sont pas mises à jour et ce qui suit est renvoyé:

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

Cela ressemble à un bug pour moi, est-ce que ça vous ressemble?


Ouais, c'est un bug. Testé sur SQL 2017 CTP 2.1 et il se comporte de la même manière que sur SQL 2016.
Dean Savović

Réponses:


12

Oui, c'est un bogue, qui semble n'affecter que les variables de table, avec une méthode d'accès à l'index bw-tree et une auto-jointure non corrélée.

Repro simplifié utilisant 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;

Plan défectueux

Notez dans le plan ci-dessus que la recherche de lignes à supprimer se termine plus tôt que prévu (seules deux lignes sont lues à partir de l'analyse). La protection Halloween est généralement correctement gérée pour l'OLTP en mémoire, il semble qu'il y ait juste un problème spécifique avec la combinaison des facteurs mentionnés ci-dessus.


Ce bogue est résolu dans SQL Server 2016 SP1 CU5 et SQL Server 2017 CU1 :

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.