W poniższym przykładzie predykaty są takie same, jednak górna instrukcja (poprawnie) zwraca 0 wierszy, dolna instrukcja zwraca 1 - nawet jeśli predykaty NIE są zgodne:
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
Dlaczego tak się dzieje?
Więcej informacji:
- Indeks nieklastrowany w górnej instrukcji NIE jest filtrowany
- CheckDB zwraca 0 problemów
- Wersja serwera:
Microsoft SQL Azure (RTM) - 12.0.2000.8 Dec 19 2018 08:43:17 Copyright (C) 2018 Microsoft Corporation
Wklej link do planu:
https://www.brentozar.com/pastetheplan/?id=S1w_rU68E
Dalsze informacje:
Uruchomiono, dbcc checktable ([transaction]) with all_errormsgs, extended_logical_checks, data_purity
co wskazuje na brak problemów.
Mogę niezawodnie odtworzyć problem z tą tabelą podczas przywracania kopii zapasowej tej bazy danych.
sql-server
azure-sql-database
columnstore
Uberzen1
źródło
źródło
Odpowiedzi:
Ten błąd nie wymaga usuwania ani zmiany nazw kolumn.
Zobaczysz również to samo zachowanie,
statusId = 100
którego nigdy nie było w żadnej wersji kolumny.Wymagania
Przykład
Każda z poniższych sytuacji pozwoli uniknąć błędu:
= NULL
db <> demo skrzypiec .
Ten błąd został naprawiony w CU15 dla SQL Server 2017 (i CU7 dla SQL Server 2016 SP2):
Poprawka: Kwerenda względem tabeli z zarówno klastrowanym indeksem magazynu kolumn, jak i nieklastrowanym indeksem magazynu danych może zwracać niepoprawne wyniki w SQL Server 2016 i 2017
źródło
To jest błąd w SQL Server. Jeśli kolumna zostanie usunięta z tabeli z klastrowanym indeksem magazynu kolumn, a następnie zostanie dodana nowa kolumna o tej samej nazwie, prawdopodobnie używa ona starej, usuniętej kolumny dla predykatu. Oto MVCE:
Ten skrypt zaczyna się od
10000
wierszy zstatusId
of1
istatusId2
of5
- następnie upuszczastatusID
kolumnę i zmienia nazwęstatusId2
nastatusId
. Na koniec wszystkie wiersze powinny miećstatusId
po 5.Ale następujące zapytanie trafia w indeks nieklastrowany ...
... i zwraca
2
wiersze (z wybranymistatusId
innymi niż sugerowane przezWHERE
klauzulę) ...... podczas gdy ten uzyskuje dostęp do magazynu kolumn i poprawnie zwraca
0
MVCE
Mam również podniesiony problem na Azure portalu sprzężenia zwrotnego :
I dla każdego, kto się z tym spotka, przebudowanie Indeks klastrowanego magazynu kolumn rozwiązuje problem:
Przebudowa CCI naprawia tylko wszelkie istniejące dane. Jeśli zostaną dodane nowe rekordy, problem pojawi się ponownie w tych rekordach; więc obecnie jedyną znaną poprawką dla tabeli jest jej całkowite odtworzenie.
źródło
and id2 = @id2
powinny gwarantować zerowych wierszy i tak jak@id2
jestnull
, ale nadal dostać 2REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);
swoje zadanie? Spowoduje to wyczyszczenie deltastore - czy problem nadal występuje w przypadku nowych wierszy dodanych później?Na podstawie planów wydaje się, że indeks magazynu kolumn został utworzony przy wyłączonym zestawie ANSI_NULLS. Tabele i indeksy zachowują ustawienie z okresu, w którym indeks został utworzony. Możesz to sprawdzić, tworząc duplikat indeksu magazynu kolumn, upewniając się, że ANSI_NULLS jest WŁĄCZONY, a następnie upuszczając oryginał lub wyłączając go.
Ale jeśli nie odkryłeś błędu programu SQL Server, jest to jedyny sposób, aby wyniki mogły się zdarzyć.
źródło