Filtre koşulu Kümelenmiş Columnstore dizinine doğru uygulanmadı


10

Aşağıdaki örnek kullanılarak tahminler aynıdır, ancak üst ifade (doğru) 0 satır döndürür, alt ifade 1 döndürür - tahminler eşleşmiyor olsa da:

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

Bu neden olabilir?

Daha fazla bilgi:

  • Üst deyimdeki Kümelenmemiş Dizin filtrelenmez
  • CheckDB 0 sayı döndürüyor
  • Sunucu Sürümü: Microsoft SQL Azure (RTM) - 12.0.2000.8 Dec 19 2018 08:43:17 Copyright (C) 2018 Microsoft Corporation

Plan bağlantısını yapıştırın:

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

Daha fazla bilgi:

dbcc checktable ([transaction]) with all_errormsgs, extended_logical_checks, data_purityHiçbir sorun gösteren koştu var .

Bu veritabanının bir yedeğini geri yüklerken sorunu bu tabloya karşı güvenilir bir şekilde yeniden oluşturabilir.


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Jack diyor ki topanswers.xyz

Yanıtlar:


7

Bu hata, sütunları bırakmayı veya yeniden adlandırmayı gerektirmez.

Ayrıca statusId = 100, sütunun herhangi bir sürümünde hiç bulunmayan aynı davranışı da görürsünüz .

Gereksinimler

  • Kümelenmiş bir sütun deposu
  • Kümelenmemiş b-ağacı endeksi
  • Sütun deposunda arama yapan bir plan
    • Delta deposundaki hedef satır (lar)
    • Zorlanmış bir SARG dışı yüklem
    • Eşitlik testi kullanılarak NULL ile karşılaştırma

Misal

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;

Aşağıdakilerden herhangi biri hatayı önler:

  • Belirtilen satır gruplarını sıkıştır seçeneğiyle yeniden düzenleme de dahil olmak üzere herhangi bir yöntemi kullanarak satırları delta deposundan taşıma
  • Açıkça reddetmek için yüklemi yazmak = NULL
  • Yüklemenin aramaya itilmesini önlemek için belgelenmemiş izleme bayrağı 9130'u etkinleştirme

keman demosu.


Bu hata SQL Server 2017 için CU15'de (ve SQL Server 2016 SP2 için CU7'de) düzeltildi :

Düzeltme: kümelenmiş sütun deposu dizini ve kümelenmemiş satır deposu dizini içeren tablo sorgu, SQL Server 2016 ve 2017'de yanlış sonuçlar döndürebilir


8

Bu SQL Server ile ilgili bir hatadır. Bir sütun, kümelenmiş bir sütun deposu dizinine sahip bir tablodan silinir ve ardından aynı ada sahip yeni bir sütun eklenirse, yüklem için eski, silinmiş sütunu kullanıyor gibi görünür. İşte MVCE:

Bu komut dosyası ile başlar 10000olan satırlar statusIdarasında 1ve statusId2içinde 5- o zaman düşer statusIDsütunu yeniden adlandırmaları statusId2için statusId. Sonuçta tüm satırlarda statusId5 olmalıdır .

Ancak aşağıdaki sorgu kümelenmemiş dizine isabet ediyor ...

select *
from example
where statusId = 1
    and total <= @filter
    and barcode = @barcode
    and id2 = @id2

... ve 2satırları döndürür (seçili statusId, WHEREmaddede belirtilenlerden farklı olarak ) ...

+-------+---------+------+-------+----------+
|  id   | barcode | id2  | total | statusId |
+-------+---------+------+-------+----------+
|     5 |    5    | NULL |  5.00 |        5 |
| 10005 |    5    | NULL |  5.00 |        5 |
+-------+---------+------+-------+----------+

... ancak bu sütun deposuna erişir ve doğru şekilde döner 0

select count(*) 
from example 
where statusId = 1

MVCE

/*Create table with clustered columnstore and non clustered rowstore*/
CREATE TABLE example
(
id        INT IDENTITY(1, 1),
barcode   CHAR(22),
id2       INT,
total     DECIMAL(10,2),
statusId  TINYINT,
statusId2 TINYINT,
INDEX cci_example CLUSTERED COLUMNSTORE,
INDEX ix_example (barcode, total)
);

/* Insert 10000 rows all with (statusId,statusId2) = (1,5) */
INSERT example
       (barcode,
        id2,
        total,
        statusId,
        statusId2)
SELECT TOP (10000) barcode = row_number() OVER (ORDER BY @@spid),
                   id2 = NULL,
                   total = row_number() OVER (ORDER BY @@spid),
                   statusId = 1,
                   statusId2 = 5
FROM   sys.all_columns c1, sys.all_columns c2;

ALTER TABLE example
  DROP COLUMN statusid
/* Now have 10000 rows with statusId2 = 5 */


EXEC sys.sp_rename
  @objname = N'dbo.example.statusId2',
  @newname = 'statusId',
  @objtype = 'COLUMN';
/* Now have 10000 rows with StatusID = 5 */

INSERT example
       (barcode,
        id2,
        total,
        statusId)
SELECT TOP (10000) barcode = row_number() OVER (ORDER BY @@spid),
                   id2 = NULL,
                   total = row_number() OVER (ORDER BY @@spid),
                   statusId = 5
FROM   sys.all_columns c1, sys.all_columns c2;
/* Now have 20000 rows with StatusID = 5 */


DECLARE @filter  DECIMAL = 5,
        @barcode CHAR(22) = '5',
        @id2     INT = NULL; 

/*This returns 2 rows from the NCI*/
SELECT *
FROM   example WITH (INDEX = ix_example)
WHERE  statusId = 1
       AND total <= @filter
       AND barcode = @barcode
       AND id2 = @id2;

/*This counts 0 rows from the Columnstore*/
SELECT COUNT(*)
FROM   example
WHERE  statusId = 1;

Azure geri bildirim portalında da bir sorunla karşılaştım :

Ve bununla karşılaşan herkes için, Kümelenmiş Sütun Deposu Dizini'nin yeniden oluşturulması sorunu giderir:

alter index cci_example on example rebuild

CCI'nin yeniden oluşturulması yalnızca mevcut verileri düzeltir. Yeni kayıtlar eklenirse, sorun yine bu kayıtlarda ortaya çıkar; şu anda tablo için bilinen tek düzeltme, tabloyu tamamen yeniden oluşturmaktır.


1
Sadece eski olanı yüklem için kullandığı sorun değil. Diğer garip şey, farklı sütunlardaki kalıntı yüklemeyi tamamen bozması, and id2 = @id2yine de sıfır satırı garanti etmelidir @id2, nullancak yine de 2
Martin Smith

RE: Düzenlemeniz 2 REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);iş yapıyor mu? Bu deltastore'u temizleyecektir - sorun bundan sonra eklenen yeni satırlarda hala oluşuyor mu?
Martin Smith

Hayır, ne yazık ki aynı sonuç gibi görünüyor?
Uberzen1

-4

Planlara dayanarak, Columnstore dizininin SET ANSI_NULLS OFF ile oluşturulduğu anlaşılıyor. Tablolar ve dizinler, ayarı dizin oluşturulduğunda olduğu gibi korur. ANSI_NULLS öğesinin AÇIK olduğundan emin olarak yinelenen bir Columnstore dizini oluşturarak, ardından orijinali bırakarak veya devre dışı bırakarak kontrol edebilirsiniz.

Ancak, bir SQL Server hatası keşfetmedikçe, sonuçların ortaya çıkmasının tek yolu budur.


2
1) filtrelenmemiş dizinlerin ANSI_NULLS ayarlarını temel tablodan ayrı tutabileceğinden ve 2) ANSI_NULLS oturumu ANSI_NULLS OFF ile oluşturulduğunda oturumun gerçekten tutarsızlıklara neden olabileceğinden emin misiniz?
Forrest

Bunu düşündüm, ancak CCI tanımını yazdığımda ayarlanmış bir seçeneği yok ve dizin tanımından önce SET ANSI_NULLS ON ile oluşturursam sonuç aynı mı?
Uberzen1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.