Sql-Server

篩選條件未正確應用於聚集列儲存索引

  • May 24, 2019

使用下面的範例,謂詞是相同的,但是頂部語句(正確)返回 0 行,底部語句返回 1 - 即使謂詞不匹配:

declare @barcode nchar(22)=N'RECB012ZUKI449M1VBJZ'  
declare @tableId int = null
declare @total decimal(10, 2) = 5.17

SELECT 1
FROM
   [dbo].[transaction] WITH (INDEX([IX_Transaction_TransactionID_PaymentStatus_DeviceID_DateTime_All]))
WHERE
   Barcode = @barcode
   AND StatusID = 1
   AND TableID = @tableID
   AND @total <= Total

SELECT 1
FROM
   [dbo].[transaction] 
WHERE
   Barcode = @barcode
   AND StatusID = 1
   AND TableID = @tableID
   AND @total <= Total

為什麼會發生這種情況?

更多資訊:

  • 頂部語句中的非聚集索引未過濾
  • CheckDB 返回 0 個問題
  • 伺服器版本:Microsoft SQL Azure (RTM) - 12.0.2000.8 Dec 19 2018 08:43:17 Copyright (C) 2018 Microsoft Corporation

粘貼計劃連結:

https://www.brentozar.com/pastetheplan/?id=S1w_rU68E

更多資訊:

已執行dbcc checktable ([transaction]) with all_errormsgs, extended_logical_checks, data_purity表明沒有問題。

還原此數據庫的備份時,我可以可靠地針對此表重現該問題。

此錯誤不需要刪除或重命名列。

您還將看到statusId = 100在任何版本的列中從未出現過的相同行為。

要求

  • 集群列儲存

  • 非聚集 b 樹索引

  • 在列儲存上執行查找的計劃

    • 增量儲存中的目標行
    • 推送的非 SARG 謂詞
    • 使用相等測試與 NULL 進行比較

例子

DROP TABLE IF EXISTS dbo.Example;
GO
CREATE TABLE dbo.Example
(
   c1 integer NOT NULL,
   c2 integer NULL,

   INDEX CCS CLUSTERED COLUMNSTORE,
   INDEX IX NONCLUSTERED (c1)
);
GO
INSERT dbo.Example
   (c1, c2)
VALUES
   (1, NULL);
GO
DECLARE @c2 integer = NULL;

-- Returns one row but should not
SELECT
   E.* 
FROM dbo.Example AS E 
   WITH (INDEX(IX))
WHERE
   E.c2 = @c2;

以下任何一項都將避免該錯誤:

  • 使用任何方法將行移出增量儲存,包括使用指定的 compress rowgroups 選項進行重組
  • 編寫謂詞以明確拒絕= NULL
  • 啟用未記錄的跟踪標誌 9130 以避免將謂詞推送到查找中

db<>小提琴展示。


此錯誤已在 SQL Server 2017 的 CU15(和 SQL Server 2016 SP2 的 CU7)中修復**:**

修復:對具有聚集列儲存索引和非聚集行儲存索引的表進行查詢可能會在​​ SQL Server 2016 和 2017 中返回不正確的結果

引用自:https://dba.stackexchange.com/questions/231460