Dies ist ein Fehler mit SQL Server. Wenn eine Spalte aus einer Tabelle mit einem Clustered Columnstore-Index gelöscht wird und dann eine neue Spalte mit demselben Namen hinzugefügt wird, wird anscheinend die alte, gelöschte Spalte für das Prädikat verwendet. Hier ist die MVCE:
Dieses Skript beginnt mit 10000
Zeilen mit statusId
von 1
und statusId2
von 5
- löscht dann die statusID
Spalte und benennt sie statusId2
in um statusId
. Am Ende sollten alle Zeilen eine statusId
5 haben.
Die folgende Abfrage trifft jedoch den nicht gruppierten Index ...
select *
from example
where statusId = 1
and total <= @filter
and barcode = @barcode
and id2 = @id2
... und gibt 2
Zeilen zurück (wobei sich die Auswahl statusId
von der in der WHERE
Klausel implizierten unterscheidet ) ...
+-------+---------+------+-------+----------+
| id | barcode | id2 | total | statusId |
+-------+---------+------+-------+----------+
| 5 | 5 | NULL | 5.00 | 5 |
| 10005 | 5 | NULL | 5.00 | 5 |
+-------+---------+------+-------+----------+
... während dieser auf den Spaltenspeicher zugreift und korrekt zurückgibt 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;
Ich habe auch ein Problem im Azure-Feedback-Portal angesprochen :
Und für alle anderen, die darauf stoßen, behebt die Neuerstellung des Clustered Columnstore-Index das Problem:
alter index cci_example on example rebuild
Durch die Neuerstellung der CCI werden nur vorhandene Daten repariert. Wenn neue Datensätze hinzugefügt werden, tritt das Problem bei diesen Datensätzen erneut auf. Derzeit besteht die einzige bekannte Lösung für die Tabelle darin, sie vollständig neu zu erstellen.