Cột thưa thớt, thời gian cpu & chỉ mục được lọc


10

Lách

Khi thực hiện một số thử nghiệm trên các cột thưa thớt, như bạn làm, có một nhược điểm về hiệu suất mà tôi muốn biết nguyên nhân trực tiếp.

DDL

Tôi đã tạo hai bảng giống hệt nhau, một bảng có 4 cột thưa và một cột không có cột thưa.

--Non Sparse columns table & NC index
CREATE TABLE dbo.nonsparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) NULL,
                      varcharval varchar(20) NULL,
                      intval int NULL,
                      bigintval bigint NULL
                      );
CREATE INDEX IX_Nonsparse_intval_varcharval
ON dbo.nonsparse(intval,varcharval)
INCLUDE(bigintval,charval);

-- sparse columns table & NC index

CREATE TABLE dbo.sparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) SPARSE NULL ,
                      varcharval varchar(20) SPARSE NULL,
                      intval int SPARSE NULL,
                      bigintval bigint SPARSE NULL
                      );

CREATE INDEX IX_sparse_intval_varcharval
ON dbo.sparse(intval,varcharval)
INCLUDE(bigintval,charval);

DML

Sau đó tôi đã chèn khoảng 2540 giá trị NON-NULL vào cả hai.

INSERT INTO dbo.nonsparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

Sau đó, tôi đã chèn các giá trị NULL 1M vào cả hai bảng

INSERT INTO dbo.nonsparse WITH(TABLOCK)  (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

Truy vấn

Thực hiện bảng không đặc biệt

Khi chạy truy vấn này hai lần trên bảng không được tạo mới:

SET STATISTICS IO, TIME ON;
SELECT  * FROM dbo.nonsparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

Các bài đọc logic hiển thị 5257 trang

(1002540 rows affected)
Table 'nonsparse'. Scan count 1, logical reads 5257, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Và thời gian cpu là 343 ms

 SQL Server Execution Times:
   CPU time = 343 ms,  elapsed time = 3850 ms.

thực hiện bảng thưa thớt

Chạy cùng một truy vấn hai lần trên bảng thưa thớt:

SELECT  * FROM dbo.sparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

Số đọc thấp hơn, 1763

(1002540 rows affected)
Table 'sparse'. Scan count 1, logical reads 1763, physical reads 3, read-ahead reads 1759, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Nhưng thời gian cpu cao hơn, 547 ms .

 SQL Server Execution Times:
   CPU time = 547 ms,  elapsed time = 2406 ms.

Kế hoạch thực hiện bảng thưa thớt

kế hoạch thực hiện bảng không thưa thớt


Câu hỏi

Câu hỏi gốc

Vì các giá trị NULL không được lưu trữ trực tiếp trong các cột thưa thớt, nên việc tăng thời gian cpu có thể là do trả về các giá trị NULL dưới dạng tập kết quả không? Hay chỉ đơn giản là hành vi như được ghi chú trong tài liệu ?

Các cột thưa thớt làm giảm các yêu cầu không gian cho các giá trị null với chi phí cao hơn để lấy các giá trị không hoàn chỉnh

Hoặc là chi phí chỉ liên quan đến đọc và lưu trữ được sử dụng?

Ngay cả khi chạy ssms với kết quả loại bỏ sau tùy chọn thực thi, thời gian cpu của lựa chọn thưa thớt vẫn cao hơn (407 ms) so với không thưa thớt (219 ms).

BIÊN TẬP

Nó có thể là chi phí chung của các giá trị không null, ngay cả khi chỉ có 2540 hiện tại, nhưng tôi vẫn không bị thuyết phục.

Điều này có vẻ là về hiệu suất tương tự, nhưng yếu tố thưa thớt đã bị mất.

CREATE INDEX IX_Filtered
ON dbo.sparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;

CREATE INDEX IX_Filtered
ON dbo.nonsparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;


    SET STATISTICS IO, TIME ON;

SELECT  charval,varcharval,intval,bigintval FROM dbo.sparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND  varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);


SELECT  charval,varcharval,intval,bigintval 
FROM dbo.nonsparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND 
                      varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);

Có vẻ như có cùng thời gian thực hiện:

 SQL Server Execution Times:
   CPU time = 297 ms,  elapsed time = 292 ms.

 SQL Server Execution Times:
   CPU time = 281 ms,  elapsed time = 319 ms.

Nhưng tại sao các logic đọc cùng một số tiền bây giờ? Không phải chỉ mục được lọc cho cột thưa thớt không lưu trữ bất cứ thứ gì ngoại trừ trường ID được bao gồm và một số trang không có dữ liệu khác?

Table 'sparse'. Scan count 1, logical reads 5785,
Table 'nonsparse'. Scan count 1, logical reads 5785

Và kích thước của cả hai chỉ số:

RowCounts   Used_MB Unused_MB   Total_MB
1000000     45.20   0.06        45.26

Tại sao những cái này có cùng kích thước? Là sự thưa thớt mất đi?

Cả hai kế hoạch truy vấn khi sử dụng chỉ mục được lọc


Thông tin thêm

select @@version

Microsoft SQL Server 2017 (RTM-CU16) (KB4508218) - 14.0.3223.3 (X64) Ngày 12 tháng 7 năm 2019 17:43:08 Bản quyền (C) 2017 Microsoft Corporation Developer Edition (64-bit) trên Windows Server 2012 R2 Datacenter 6.3 (Bản dựng 9600 :) (Hypervisor)

Trong khi chạy các truy vấn và chỉ chọn trường ID , thời gian cpu có thể so sánh được, với số lần đọc logic thấp hơn cho bảng thưa thớt.

Kích thước của các bảng

SchemaName  TableName   RowCounts   Used_MB Unused_MB   Total_MB
dbo         nonsparse   1002540     89.54   0.10        89.64
dbo         sparse      1002540     27.95   0.20        28.14

Khi buộc chỉ mục được nhóm hoặc không được bao gồm, chênh lệch thời gian cpu vẫn còn.


1
Bạn có thể có được các kế hoạch cho truy vấn sau chỉnh sửa?
George.Palacios

1
@ George.Palacios đã thêm chúng :)
Randi Vertongen

Câu trả lời:


6

Hay chỉ đơn giản là hành vi như được ghi chú trong tài liệu?

Có vẻ như vậy. "Chi phí" được đề cập trong tài liệu dường như là chi phí hoạt động của CPU.

Cấu hình hai truy vấn, truy vấn thưa thớt đã lấy mẫu 367 ms CPU, trong khi truy vấn không thưa thớt có CPU có 284 ms. Đó là sự khác biệt của 83 ms.

ảnh chụp màn hình từ Perfview hiển thị tổng số CPU cho luồng chạy truy vấn

Phần lớn ở đâu?

Cả hai hồ sơ trông rất giống nhau cho đến khi họ nhận được sqlmin!IndexDataSetSession::GetNextRowValuesInternal. Tại thời điểm đó, mã thưa thớt đi xuống một đường dẫn chạy sqlmin!IndexDataSetSession::GetDataLong, gọi một số hàm trông giống như chúng liên quan đến tính năng cột thưa thớt ( HasSparseVector, StoreColumnValue) và thêm tới (42 + 11 =) 53 ms.

Ảnh chụp màn hình chênh lệch CPU cho cột thưa thớt

Tại sao những cái này có cùng kích thước? Là sự thưa thớt mất đi?

Vâng, có vẻ như tối ưu hóa lưu trữ thưa thớt không chuyển sang các chỉ mục không được bao gồm khi cột thưa được sử dụng làm khóa chỉ mục. Vì vậy, các cột khóa chỉ mục không bao gồm chiếm kích thước đầy đủ của chúng bất kể độ thưa thớt, nhưng các cột được bao gồm chiếm không gian nếu chúng thưa thớt và NULL.

Nhìn vào DBCC PAGEđầu ra từ một trang chỉ mục được nhóm với các cột thưa có giá trị NULL, tôi có thể thấy rằng độ dài bản ghi là 11 (4 cho ID + 7 cho chi phí trên mỗi bản ghi tiêu chuẩn):

Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 11

Đối với chỉ mục được lọc, bản ghi luôn là 40, là tổng kích thước của tất cả các cột chính (ID 4 byte + 20 byte charval + 4 byte varval + 4 byte intval + 8 byte intval = 40 byte).

Vì một số lý do, DBCC PAGEkhông bao gồm chi phí 7 byte trong "Kích thước bản ghi" cho các bản ghi chỉ mục:

Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 40

Kích thước chỉ mục không được lọc nhỏ hơn (4 byte ID + 4 byte intval + 4 byte varcharval = 12 byte) vì hai trong số các cột thưa thớt được bao gồm các cột, một lần nữa được tối ưu hóa độ thưa:

Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 12

Tôi đoán sự khác biệt này trong hành vi xếp hàng với một trong những hạn chế được liệt kê trong trang tài liệu:

Một cột thưa thớt không thể là một phần của một chỉ mục được nhóm hoặc một chỉ mục khóa chính duy nhất

Chúng được phép là khóa trong các chỉ mục không bao gồm, nhưng chúng không được lưu trữ, uh, thưa thớt.


2
Đẹp quá Cảm ơn một lần nữa!
Randi Vertongen
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.