นี่เป็นข้อผิดพลาดกับ SQL Server หากคอลัมน์ถูกลบออกจากตารางที่มีดัชนี columnstore แบบคลัสเตอร์จากนั้นคอลัมน์ใหม่จะถูกเพิ่มด้วยชื่อเดียวกันดูเหมือนว่าคอลัมน์นั้นจะใช้คอลัมน์เก่าและลบสำหรับเพรดิเคต นี่คือ MVCE:
สคริปต์นี้จะเริ่มออกด้วย10000
แถวที่มีstatusId
ของ1
และstatusId2
ของ5
- แล้วหยดstatusID
คอลัมน์และเปลี่ยนชื่อไปstatusId2
statusId
ดังนั้นในตอนท้ายแถวทั้งหมดควรมีค่าstatusId
เท่ากับ 5
แต่เคียวรีต่อไปนี้จะเข้าชมดัชนีที่ไม่ทำคลัสเตอร์ ...
select *
from example
where statusId = 1
and total <= @filter
and barcode = @barcode
and id2 = @id2
... และส่งคืน2
แถว (ที่มีการเลือกstatusId
แตกต่างจากนัยโดยWHERE
ข้อ) ...
+-------+---------+------+-------+----------+
| id | barcode | id2 | total | statusId |
+-------+---------+------+-------+----------+
| 5 | 5 | NULL | 5.00 | 5 |
| 10005 | 5 | NULL | 5.00 | 5 |
+-------+---------+------+-------+----------+
... ในขณะที่อันนี้เข้าถึง columnstore และส่งกลับอย่างถูกต้อง 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 :
และสำหรับใครก็ตามที่พบสิ่งนี้การสร้างดัชนีคอลัมน์ที่เก็บเป็นกลุ่มใหม่จะช่วยแก้ปัญหาได้:
alter index cci_example on example rebuild
การสร้าง CCI ใหม่จะแก้ไขข้อมูลที่มีอยู่เท่านั้น หากมีการเพิ่มระเบียนใหม่ปัญหาจะเกิดขึ้นอีกครั้งในบันทึกเหล่านี้ ดังนั้นในปัจจุบันการแก้ไขที่ทราบเพียงอย่างเดียวสำหรับตารางคือการสร้างใหม่ทั้งหมด