Falsches Verhalten von SQL Server 2016 mit speicheroptimierten Tabellen

13

Bitte schauen Sie sich die folgende SQL-Abfrage an:

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

Bei der Ausführung unter SQL Server 2014 (12.0.4100.1 X64) verhält sich UPDATEdie Abfrage wie erwartet und das folgende gültige Ergebnis wird zurückgegeben:

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

Bei der Ausführung unter SQL Server 2016 (13.0.4001.0 X64) werden jedoch nicht alle Zeilen aktualisiert und Folgendes zurückgegeben:

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

Das sieht für mich wie ein Käfer aus, sieht es für dich so aus?

Dmitry Savchenko
quelle
Ja, das ist ein Fehler. Getestet auf SQL 2017 CTP 2.1 und es verhält sich genauso wie auf SQL 2016.
Dean Savović

Antworten:

12

Ja, es handelt sich um einen Fehler, der nur Tabellenvariablen zu betreffen scheint, mit einer bw-Tree-Indexzugriffsmethode und einem nicht korrelierten Self-Join.

Vereinfachte Reproduktion mit 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;

Fehlerhafter Plan

Beachten Sie, dass im obigen Plan die Suche nach zu löschenden Zeilen früher als erwartet beendet wird (nur zwei Zeilen werden vom Scan gelesen). Der Halloween-Schutz wird für In-Memory-OLTP im Allgemeinen korrekt gehandhabt. Es scheint nur ein spezifisches Problem mit der Kombination der oben genannten Faktoren zu geben.


Dieser Fehler wird festgelegt in SQL Server 2016 SP1 CU5 und SQL Server 2017 CU1 :

Paul White Monica wieder einsetzen
quelle