Làm cách nào để xem dữ liệu trong bảng SQL Server có được nén trang không?


8

Đây là một câu hỏi tiếp theo cho một câu hỏi mà tôi đã hỏi ngày hôm qua: Tôi có thể chèn số lượng lớn vào một bảng nén trang trống và có được nén hoàn toàn không? Câu trả lời cho câu hỏi đó (được diễn giải từ câu trả lời xuất sắc của Randi Vertongen) là có, nhưng nó yêu cầu bộ chèn số lượng lớn phải có khóa cấp độ bảng; mặt khác, chèn số lượng lớn sẽ khóa cấp hàng và chỉ thực hiện nén dữ liệu hàng. Điều này đặt ra câu hỏi: làm thế nào tôi có thể biết sau đó áp dụng nén nào?

Dưới đây là các bước để tạo dữ liệu nén hàng trong bảng nén theo lý thuyết:
1. Tạo bảng có DATA_COMPRESSION=PAGEvà không sử dụng sp_tableoptionđể bật tùy chọn "khóa bảng khi tải hàng loạt" cho bảng này.
2. Sử dụng bcp để chèn số lượng lớn dữ liệu từ một tệp phẳng vào bảng mới, nhưng không chỉ định -h TABLOCKtùy chọn khóa bảng.

Kết quả là một bảng trong đó dữ liệu được nén ở cấp hàng (nhỏ hơn bảng không nén nhưng lớn hơn bảng nén trang), nhưng kiểm tra sys.allocation_unitsbảng danh mục cho thấy nén dữ liệu dưới dạng trang.

Câu hỏi

Khi phân bổ dữ liệu của bảng là để nén trang như trong kịch bản này, tôi có thể làm gì để tìm hiểu xem dữ liệu trong bảng đó có được nén trang không?


Ngoài ra, đối với SQL 2016+, bạn nên xem xét một chỉ mục cửa hàng cột được phân cụm cho các tình huống liên quan đến tải và nén hàng loạt.
David Browne - Microsoft

Câu trả lời:


13

Để xem các trang dữ liệu có thực sự được nén "TRANG" hay không, bạn có thể sử dụng DMF không có giấy tờ sys.dm_db_database_page_allocations(). Các is_page_compressedlĩnh vực có chứa các thông tin mà bạn đang tìm kiếm. Bạn sẽ cần sử dụng DETAILEDchế độ (tức là tham số thứ 5) hoặc các giá trị trong trường đó sẽ là tất cả NULL.

Để rõ ràng (dựa trên cách diễn đạt câu hỏi, "tôi có thể làm gì để tìm hiểu xem dữ liệu trong bảng đó có bị nén trang không?"), Đây không phải là vấn đề tất cả hoặc không: áp dụng nén trang được áp dụng trên mỗi trang dữ liệu , do đó bạn có thể không có tệp nào được nén, tất cả được nén hoặc bất kỳ kết hợp nào ở giữa. Vì vậy, bạn cần phải xem tất cả các trang. Và không, bạn không nhất thiết phải cho rằng một trang nén không phải trang chỉ ra rằng bạn cần REBUILDbởi vì một trang không được điền sẽ không nén.

Ví dụ:

SELECT [is_page_compressed]
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED');

Sau đây cho thấy các trang dữ liệu ban đầu không được nén trang, nhưng chúng nằm sau REBUILDthao tác:

USE [tempdb];

-- DROP TABLE dbo.CompressedHeap;
CREATE TABLE dbo.CompressedHeap
(
  ID INT IDENTITY(1, 1) NOT NULL,
  String sysname,
  [MaxLength] SMALLINT,
  [Type] VARCHAR(5)
) WITH (DATA_COMPRESSION = PAGE);


INSERT INTO dbo.CompressedHeap ([String], [MaxLength], [Type])
  SELECT col.[name], col.[max_length], obj.[type]
  FROM   master.sys.columns col
  CROSS JOIN master.sys.objects obj;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 394 pages


ALTER TABLE dbo.CompressedHeap REBUILD;


SELECT [is_page_compressed], *
FROM   sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID(N'dbo.CompressedHeap'),
                                           0, 1, 'DETAILED')
WHERE  [is_iam_page] = 0
AND    [is_allocated] = 1;
-- 179 pages

1
Đó chính xác là những gì tôi cần, cảm ơn bạn rất nhiều! Tôi đã kiểm tra một số bảng thực tế của mình và các bảng được tải mà không khóa bảng có 0% trang được nén trong khi các bảng mới mà tôi đã tải với khóa bảng có 99,8% số trang được nén (và ít hơn rất nhiều trong số chúng), giống như bạn diễn tả.
Caitlin M. Shaw

0

Bạn có thể tìm thấy mức nén trong sys.partitions dmv

SELECT t.name AS tablename,
       i.name AS indexname,
       p.data_compression_desc
FROM sys.tables AS t
INNER JOIN sys.indexes AS i
     ON t.object_id = i.object_id
INNER JOIN sys.partitions AS p
     ON i.object_id = p.object_id
        AND i.index_id = p.index_id;

1
Đáng buồn thay, đây là một kịch bản trong đó nén thực tế trên các trang dữ liệu không phải là những gì được liệt kê trong sys.partitions.
Caitlin M. Shaw

1
Xin chào Bob (và @ CaitlinM.Shaw): giá trị trong sys.partitionsphải là loại nén dữ liệu lý tưởng / được yêu cầu. Nhưng vì giá trị đó chỉ ở cấp phân vùng, nên nó không thể hiển thị giá trị hiện tại trên mỗi trang, cũng như giá trị hiện tại trên mỗi hàng, cả hai giá trị này có thể khác nhau trong mỗi phân vùng.
Solomon Rutzky

thật tốt khi biết điều đó, cảm ơn
Bob Klimes
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.