Используя приведенный ниже пример, предикаты одинаковы, однако верхний оператор (правильно) возвращает 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
что указывает на отсутствие проблем.
Я могу надежно воспроизвести проблему с этой таблицей при восстановлении резервной копии этой базы данных.
sql-server
azure-sql-database
columnstore
Uberzen1
источник
источник
Ответы:
Эта ошибка не требует удаления или переименования столбцов.
Вы также увидите то же поведение,
statusId = 100
которого никогда не было ни в одной версии столбца.Требования
пример
Любое из следующего позволит избежать ошибки:
= NULL
БД <> Fiddle demo.
Эта ошибка была исправлена в CU15 для SQL Server 2017 (и CU7 для SQL Server 2016 с пакетом обновления 2):
ИСПРАВЛЕНИЕ: Запрос к таблице с кластеризованным индексом хранилища столбцов и некластеризованным индексом хранилища строк может возвращать неверные результаты в SQL Server 2016 и 2017
источник
Это ошибка с SQL Server. Если столбец удаляется из таблицы с кластеризованным индексом хранилища столбцов, а затем добавляется новый столбец с тем же именем, он, похоже, использует старый, удаленный столбец для предиката. Вот MVCE:
Этот скрипт начинается со
10000
строк сstatusId
of1
иstatusId2
of5
- затем удаляетstatusID
столбец и переименовываетсяstatusId2
вstatusId
. Таким образом, в конце все строки должны иметьstatusId
5.Но следующий запрос попадает в некластеризованный индекс ...
... и возвращает
2
строки (с выбранным,statusId
отличным от подразумеваемогоWHERE
предложением) ...... тогда как этот получает доступ к columnstore и правильно возвращает
0
MVCE
Я также поднял вопрос на портале отзывов Azure :
И для всех, кто столкнулся с этим, перестройка Clustered Columnstore Index решает проблему:
Восстановление CCI только исправляет любые существующие данные. Если новые записи добавляются, проблема снова возникает на этих записях; поэтому в настоящее время единственным известным исправлением для таблицы является ее полное воссоздание.
источник
and id2 = @id2
должно гарантировать нулевые строки в любом случае, как@id2
есть,null
но вы все равно получаете 2REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);
свою работу? Это очистит deltastore - проблема все еще возникает для новых строк, добавленных после этого?Исходя из планов, создается впечатление, что индекс Columnstore был создан с параметром SET ANSI_NULLS OFF. Таблицы и индексы сохраняют настройку, которая была при создании индекса. Вы можете проверить, создав дубликат индекса Columnstore, убедившись, что ANSI_NULLS включен, а затем либо сбросив оригинал, либо отключив его.
Но, если вы не обнаружили ошибку SQL Server, это единственный способ получить результаты.
источник