Mục đích của cột Uniq1002 này trong lần quét chỉ mục này là gì?


7

Thực hiện các repro sau:

USE tempdb;

IF OBJECT_ID(N'dbo.t', N'U') IS NOT NULL
DROP TABLE dbo.t
GO
CREATE TABLE dbo.t
(
    id int NOT NULL 
        PRIMARY KEY 
        NONCLUSTERED 
        IDENTITY(1,1)
    , col1 datetime NOT NULL
    , col2 varchar(800) NOT NULL
    , col3 tinyint NULL
    , col4 sysname NULL
);

INSERT INTO dbo.t (
      col1
    , col2
    , col3
    , col4
    ) 
SELECT TOP(100000) 
      CONVERT(datetime, 
         DATEADD(DAY, CONVERT(int, CRYPT_GEN_RANDOM(1)), '2000-01-01 00:00:00'))
    , replicate('A', 800)
    , sc2.bitpos
    , CONVERT(sysname, CHAR(65 + CRYPT_GEN_RANDOM(1) % 26) 
        + CHAR(65 + CRYPT_GEN_RANDOM(1) % 26) 
        + CHAR(65 + CRYPT_GEN_RANDOM(1) % 26))
FROM sys.syscolumns sc
    CROSS JOIN sys.syscolumns sc2;

Ở đây tôi đang thêm một chỉ mục được nhóm vào một tập hợp các cột không phải là duy nhất và chỉ mục không phân cụm một cột điển hình:

CREATE CLUSTERED INDEX t_cx 
ON dbo.t (col1, col2, col3);

CREATE INDEX t_c1 ON dbo.t(col4); 

Truy vấn này buộc SQL Server thực hiện tra cứu vào chỉ mục được nhóm. Xin vui lòng tha thứ cho việc sử dụng gợi ý chỉ mục, đó là cách nhanh nhất để có được lời trách móc:

SELECT id
    , col1
    , col2
    , col3
FROM dbo.t aad WITH (INDEX = t_c1)
WHERE col4 = N'JSB'
    AND col1 > N'2019-05-30 00:00:00';

Các kế hoạch truy vấn thực tế chương trình một cột không tồn tại trong danh sách Output cho chỉ số nonclustered quét:

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

Rõ ràng, điều này đại diện cho uniqifier được sử dụng trong chỉ mục cụm không duy nhất. Có phải vậy không? Là một cột có tên như vậy luôn luôn là uniqifier chỉ mục cụm?

Câu trả lời:


9

Rõ ràng, điều này đại diện cho uniqifier được sử dụng trong chỉ mục cụm không duy nhất. Có phải vậy không?

Đúng.

Mục đích của cột Uniq1002 này trong lần quét chỉ mục này là gì?

Mỗi hàng trong chỉ mục không bao gồm phải được liên kết với chính xác một hàng trong bảng cơ sở để Tra cứu Dấu trang (RID hoặc Khóa) hoạt động chính xác. Ánh xạ này được cung cấp bởi "trình định vị hàng".

Đối với các bảng heap, bộ định vị hàng là RID. Đối với các bảng lưu trữ hàng được phân cụm, đó là khóa phân cụm (bao gồm cả bộ duy nhất khi cần thiết).

Để Tra cứu khóa trong kế hoạch của bạn hoạt động, nó phải có quyền truy cập vào trình định vị hàng. Điều này bao gồm trình xác định duy nhất , do đó nó phải được phát ra bằng cách quét chỉ mục không bao gồm .

Trình duy nhất được lưu trữ trong phần có độ dài thay đổi của hàng để nó chỉ chiếm không gian khi cần thiết (tức là khi một khóa trùng lặp thực sự tồn tại).

Là một cột có tên như vậy luôn luôn là duy nhất chỉ mục cụm?

Đúng. Cột uniquifier luôn được đặt tên UniqXXXX. Bộ định vị hàng liên kết với bảng heap được đặt tên BmkXXXX. Bộ định vị hàng cho một bảng cột được đặt tên ColStoreLocXXXX.


Quan sát người duy nhất

Có thể quan sát trực tiếp các giá trị của trình duy nhất trên các phiên bản SQL Server có chứa query_trace_column_valuesSự kiện mở rộng chức năng .

Sự kiện không có giấy tờ và không được hỗ trợ này nằm trong kênh Debug . Nó được giới thiệu với SQL Server 2016 và đã ngừng hoạt động xung quanh CU11 của SQL Server 2017.

Ví dụ:

CREATE TABLE #T (c1 integer NULL INDEX ic1 CLUSTERED, c2 integer NULL INDEX ic2 UNIQUE, c3 integer NULL);
GO
INSERT #T
    (c1, c2, c3)
VALUES 
    (100, 101, 0),
    (100, 102, 1),
    (100, 103, 2);
GO
DBCC TRACEON (2486);
SET STATISTICS XML ON;
SELECT T.* FROM #T AS T WITH (INDEX(ic2));
SET STATISTICS XML OFF;
DBCC TRACEOFF (2486);
GO
DROP TABLE #T;

Có kế hoạch:

Kế hoạch

Nó tạo đầu ra sự kiện như sau trên SQL Server 2016:

Đầu ra sự kiện


2

Để SQL Server tạo một chỉ mục cụm không duy nhất , một "cột" ẩn được thêm vào cấu trúc vật lý của chỉ mục được phân cụm. Cột ẩn đó được gọi là uniqifier và như tên của nó ngụ ý, cung cấp một cơ chế để đảm bảo rằng mỗi hàng trong chỉ mục cụm là duy nhất.

Khi bạn thấy cột đó hiển thị trong kế hoạch truy vấn, đó là một chỉ báo tuyệt vời rằng các cột khóa phân cụm chưa được xác định là duy nhất. Có thể đó là vì sự kết hợp của các cột được biết là không phải là duy nhất. Cũng có thể người thiết kế bảng chỉ cần quên thêm UNIQUEvòng loại vào CREATE CLUSTERED INDEXcâu lệnh.

Trong thực tế, nếu chúng ta tạo lại repro ở trên với một chỉ mục được nhóm duy nhất, thì Uniq1002cột không còn xuất hiện trong kế hoạch truy vấn:

USE tempdb;

IF OBJECT_ID(N'dbo.t', N'U') IS NOT NULL
DROP TABLE dbo.t
GO
CREATE TABLE dbo.t
(
    id int NOT NULL 
        PRIMARY KEY 
        NONCLUSTERED 
        IDENTITY(1,1)
    , col1 datetime NOT NULL
    , col2 varchar(800) NOT NULL
    , col3 int NULL
    , col4 sysname NULL
);

INSERT INTO dbo.t (
      col1
    , col2
    , col3
    , col4
    ) 
SELECT TOP(100000) 
      CONVERT(datetime, DATEADD(DAY, CONVERT(int, CRYPT_GEN_RANDOM(1)), '2000-01-01 00:00:00'))
    , replicate('A', 800)
    , CONVERT(int, CRYPT_GEN_RANDOM(4))
    , CONVERT(sysname, CHAR(65 + CRYPT_GEN_RANDOM(1) % 26) 
        + CHAR(65 + CRYPT_GEN_RANDOM(1) % 26) 
        + CHAR(65 + CRYPT_GEN_RANDOM(1) % 26))
FROM sys.syscolumns sc
    CROSS JOIN sys.syscolumns sc2;

Đây là chỉ số cụm UNIITE:

CREATE UNIQUE CLUSTERED INDEX t_cx 
ON dbo.t (col1, col2, col3);

CREATE INDEX t_c1 ON dbo.t(col4); 

Và truy vấn:

SELECT id
    , col1
    , col2
    , col3
FROM dbo.t aad WITH (INDEX = t_c1)
WHERE col4 = N'JSB'
    AND col1 > N'2019-05-30 00:00:00';

Bây giờ kế hoạch cho thấy điều này cho các cột đầu ra quét chỉ mục không phân cụm:

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

Khi một chỉ mục cụm không duy nhất được tạo, uniqifier sẽ tự động được thêm vào. Uniqifier cũng được thêm vào mọi chỉ mục không được nhóm, mặc dù bạn không thể "nhìn thấy" nó bằng cách xem các thuộc tính của chỉ mục hoặc bằng cách "tạo kịch bản" cho chỉ mục.

Uniqifier là một cột bốn byte chứa một số nguyên được tự động tăng lên phía sau các cảnh cho mỗi hàng được chèn vào bảng. Hàng đầu tiên được chèn không yêu cầu uniqifier; chỉ các hàng được thêm vào sau hàng đầu tiên có bộ uniqifier.

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.