メモリ最適化テーブルを使用した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

これはバグのように見えますが、あなたにはそう見えますか?


ええ、これはバグです。CTP 2.1 SQL 2017の上にそれをテストし、それがSQL 2016にないとして、それは同じように動作します
ディーンSavović

回答:


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;

欠陥のある計画

上記の計画では、削除する行の検索が予想よりも早く終了することに注意してください(スキャンから2行のみが読み取られます)。通常、ハロウィーン保護はインメモリOLTPに対して正しく処理されますが、上記の要因の組み合わせには特定の問題があるようです。


このバグは、SQL Server 2016 SP1 CU5およびSQL Server 2017 CU1で修正されています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.