Cột định danh trong chỉ mục cột


9

Tôi có một bảng IMO cực lớn (~ 137 triệu hàng) với rất nhiều dữ liệu lặp lại, rất nhiều NULLcột, v.v.

Tôi đang xem xét việc khám phá điều này bằng cách sử dụng một bảng có a COLUMNSTORE INDEXvà tôi có một IDENTITYcột trong bảng gốc, đây là cột duy nhất của tôi trong đó mỗi hàng là duy nhất.

Tôi nên để cột này ra hoặc bao gồm nó? Tôi đã đọc rằng bạn muốn bao gồm tất cả các hàng của bảng của bạn vào COLUMNSTORE INDEXnhưng tôi cũng đã đọc rằng các ứng cử viên tốt nhất là các cột có nhiều hàng không độc đáo.

Đây chỉ là một ứng cử viên xấu cho một COLUMNSTORE INDEX?

Tôi đang sử dụng SQL Server 2012, vì vậy đây là một cửa hàng cột không bao gồm. Tôi chỉ khám phá những cách tốt hơn để lưu trữ dữ liệu này. Các cập nhật không tồn tại, mặc dù các hàng mới sẽ được thêm định kỳ thông qua quy trình ELT vì vậy tôi cho rằng một số công việc sẽ được thực hiện ở đó. Một số người khai thác dữ liệu này và tạo ra các báo cáo khổng lồ, rất nhiều lần quét các hàng, đưa máy chủ đến thu thập dữ liệu vào những thời điểm buộc chúng tôi phải giảm tải một bản sao hàng ngày cho máy chủ thứ cấp.


1
Là cột nhận dạng trên bảng gốc cũng là chỉ mục cụm của bạn? Nếu vậy, SQL Server sẽ tự động đưa cột đó vào bất kỳ chỉ mục cửa hàng cột không phân cụm nào, ngay cả khi bạn không yêu cầu rõ ràng về nó. Điều này hơi giống với cách các cột chỉ mục được phân cụm sẽ được bao gồm trong một chỉ mục cây b không được phân cụm, nhưng dữ liệu sẽ được lưu trữ dưới dạng các phân đoạn cột được nén thực tế trong trường hợp này. Xem dba.stackexchange.com/questions/103722/ Khăn để biết thêm thông tin.
Geoff Patterson

137 million rowslà lớn nhưng có thể quản lý được. Bạn đã xem xét phân vùng bảng và đặt nó trên các nhóm fileg khác nhau? Chỉ mục cột trong sql 2012 không thể ghi được, vì vậy bạn sẽ gặp vấn đề - bạn phải loại bỏ và tạo lại nó. Tôi không nói rằng cột sẽ là xấu, nhưng tốt hơn là khám phá các tùy chọn khác là tốt.
Kin Shah

Câu trả lời:


11

Các cột danh tính không thực sự được nén trong Chỉ mục của Cột trong SQL Server 2012 hoặc SQL Server 2014. Tất cả sẽ thực sự phụ thuộc vào khối lượng công việc mà bạn đang gặp phải. Nếu khối lượng công việc của bạn sẽ bao gồm cột nhận dạng, thì bạn có thể tận dụng rất tốt việc loại bỏ Phân đoạn.

Từ quan điểm nén - Cột lưu trữ sẽ cung cấp cho bạn khả năng nén tốt hơn so với trang thường làm. Điển hình. Vui lòng kiểm tra nó trước khi tiến tới sản xuất.

Vấn đề lớn nhất của bạn trong SQL Server 2012 sẽ là việc triển khai Batch Mode rất yếu và bạn không thể làm gì về nó.


7
Chào mừng bạn!
Aaron Bertrand

3

Tôi không thể cưỡng lại việc tham gia Niko với một câu trả lời khác (chào mừng, Niko!). Nói chung, tôi đồng ý với Niko rằng các giới hạn chế độ hàng loạt trong SQL 2012 (nếu Niko sẽ không liên kết với blog của riêng anh ấy, tôi sẽ :)) có thể là một mối quan tâm lớn. Nhưng nếu bạn có thể sống với những điều đó và có toàn quyền kiểm soát mọi truy vấn bạn đang viết trên bảng để kiểm tra cẩn thận thì cột đó có thể hoạt động cho bạn trong SQL 2012.

Theo như các câu hỏi cụ thể của bạn về cột định danh, tôi thấy rằng cột nhận dạng nén rất tốt và rất khuyến khích đưa nó vào chỉ mục của cửa hàng cột trong bất kỳ thử nghiệm ban đầu nào của bạn. (Lưu ý rằng nếu cột danh tính cũng là chỉ mục được nhóm của cây b của bạn, thì nó sẽ tự động được bao gồm trong chỉ mục của cửa hàng cột không được phân cụm .)

Để tham khảo, đây là các kích thước tôi quan sát được cho ~ 10MM hàng dữ liệu cột nhận dạng. Kho lưu trữ cột được tải để loại bỏ phân đoạn tối ưu nén thành 26MB (so với 113 MB để PAGEnén bảng lưu trữ hàng hóa) và thậm chí kho lưu trữ cột được xây dựng trên cây b được đặt hàng ngẫu nhiên chỉ có 40 MB. Vì vậy, điều này cho thấy lợi ích nén rất lớn, thậm chí qua SQL nén cây b tốt nhất phải cung cấp và ngay cả khi bạn không muốn căn chỉnh dữ liệu của mình để loại bỏ phân đoạn tối ưu (trước tiên bạn sẽ làm bằng cách tạo cây b và sau đó xây dựng cửa hàng cột của bạn với MAXDOP1).

nhập mô tả hình ảnh ở đây

Dưới đây là toàn bộ kịch bản tôi đã sử dụng trong trường hợp bạn muốn chơi xung quanh:

-- Confirm SQL version
SELECT @@version
--Microsoft SQL Server 2012 - 11.0.5613.0 (X64) 
--  May  4 2015 19:05:02 
--  Copyright (c) Microsoft Corporation
--  Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )


-- Create a columnstore table with identity column that is the primary key
-- This will yield 10 columnstore segments @ 1048576 rows each
SELECT i = IDENTITY(int, 1, 1), ROW_NUMBER() OVER (ORDER BY randGuid) as randCol
INTO #testIdentityCompression_sortedColumnstore
FROM (
    SELECT TOP 10485760 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS randI, NEWID() AS randGuid
    FROM master..spt_values v1
    CROSS JOIN master..spt_values v2
    CROSS JOIN master..spt_values v3
) r
ORDER BY r.randI
GO
ALTER TABLE #testIdentityCompression_sortedColumnstore
ADD PRIMARY KEY (i)
GO
-- Load using a pre-ordered b-tree and one thread for optimal segment elimination
-- See http://www.nikoport.com/2014/04/16/clustered-columnstore-indexes-part-29-data-loading-for-better-segment-elimination/
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_sortedColumnstore ON #testIdentityCompression_sortedColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create another table with the same data, but randomly ordered
SELECT *
INTO #testIdentityCompression_randomOrderColumnstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_randomOrderColumnstore
ADD UNIQUE CLUSTERED (randCol)
GO
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_randomOrderColumnstore ON #testIdentityCompression_randomOrderColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create a b-tree with the identity column data and no compression
-- Note that we copy over only the identity column since we'll be looking at the total size of the b-tree index
-- If anything, this gives an unfair "advantage" to the rowstore-page-compressed version since more
-- rows fit on a page and page compression rates should be better without the "randCol" column.
SELECT i
INTO #testIdentityCompression_uncompressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_uncompressedRowstore
ADD PRIMARY KEY (i)
GO

-- Create a b-tree with the identity column and page compression
SELECT i
INTO #testIdentityCompression_compressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_compressedRowstore
ADD PRIMARY KEY (i)
WITH (DATA_COMPRESSION = PAGE)
GO

-- Compare all the sizes!
SELECT OBJECT_NAME(p.object_id, 2) AS tableName, COUNT(*) AS num_segments, SUM(on_disk_size / (1024.*1024.)) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.column_store_segments s
    ON s.partition_id = p.partition_id
    AND s.column_id = 1
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_sortedColumnstore'),OBJECT_ID('tempdb..#testIdentityCompression_randomOrderColumnstore'))
GROUP BY p.object_id
UNION ALL
SELECT OBJECT_NAME(p.object_id, 2) AS tableName
    , NULL AS num_segments
    , (a.total_pages*8.0) / (1024.0) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.allocation_units a
    ON a.container_id = p.partition_id
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_compressedRowstore'),OBJECT_ID('tempdb..#testIdentityCompression_uncompressedRowstore'))
ORDER BY 3 ASC
GO

Cảm ơn bạn vì tất cả các câu trả lời tuyệt vời, ngay bây giờ tôi đã quyết định giữ lại cho đến khi tôi có thể truy cập ít nhất máy chủ sql 2014. chúng tôi đang đẩy mạnh nâng cấp để tôi hy vọng trong năm tới chúng tôi có thể làm điều này.
Don
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.