Các chỉ mục của SQL Server - tăng dần hoặc giảm dần, nó tạo ra sự khác biệt gì?


138

Khi bạn tạo một chỉ mục trên một cột hoặc số cột trong MS SQL Server (Tôi đang sử dụng phiên bản 2005), bạn có thể chỉ định rằng chỉ mục trên mỗi cột sẽ tăng dần hoặc giảm dần. Tôi đang có một thời gian khó hiểu tại sao sự lựa chọn này thậm chí còn ở đây. Sử dụng các kỹ thuật sắp xếp nhị phân, sẽ không phải là một tra cứu nhanh như vậy sao? Sự khác biệt nào làm cho tôi chọn thứ tự nào?


Câu trả lời:


136

Điều này chủ yếu quan trọng khi được sử dụng với các chỉ mục tổng hợp:

CREATE INDEX ix_index ON mytable (col1, col2 DESC);

có thể được sử dụng cho một trong hai:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2 DESC

hoặc là:

SELECT  *
FROM    mytable
ORDER BY
        col1 DESC, col2

, nhưng không phải cho:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2

Một chỉ mục trên một cột có thể được sử dụng một cách hiệu quả để sắp xếp theo cả hai cách.

Xem bài viết trong blog của tôi để biết chi tiết:

Cập nhật:

Trong thực tế, điều này có thể quan trọng ngay cả đối với một chỉ mục cột, mặc dù nó không quá rõ ràng.

Hãy tưởng tượng một chỉ mục trên một cột của một bảng được nhóm:

CREATE TABLE mytable (
       pk INT NOT NULL PRIMARY KEY,
       col1 INT NOT NULL
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)

Chỉ mục trên col1giữ các giá trị được sắp xếp col1cùng với các tham chiếu đến các hàng.

Vì bảng được nhóm, các tham chiếu đến các hàng thực sự là các giá trị của pk. Họ cũng được sắp xếp trong mỗi giá trị của col1.

Điều này có nghĩa là các lá của chỉ mục thực sự được đặt hàng (col1, pk)và truy vấn này:

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk

không cần phân loại.

Nếu chúng ta tạo chỉ mục như sau:

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)

, sau đó các giá trị của col1sẽ được sắp xếp giảm dần, nhưng các giá trị pkbên trong mỗi giá trị col1sẽ được sắp xếp tăng dần.

Điều này có nghĩa là truy vấn sau:

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk DESC

có thể được phục vụ bởi ix_mytable_col1_descnhưng không phải bởi ix_mytable_col1.

Nói cách khác, các cột tạo thành một CLUSTERED INDEXtrên bất kỳ bảng nào luôn là các cột theo sau của bất kỳ chỉ mục nào khác trên bảng đó.


1
Khi bạn nói "không phải cho ..." bạn có nghĩa là nó không hoạt động hoặc hiệu suất sẽ rất tệ?
Neil N

5
Tôi có nghĩa là chỉ mục sẽ không được sử dụng cho truy vấn. Bản thân truy vấn sẽ hoạt động, nhưng hiệu suất sẽ kém.
Quassnoi

1
Trong phần đầu tiên, ví dụ thứ hai có nên nói "ĐẶT HÀNG B colNG col1 DESC, col2 DESC" không?
Mitch Wheat

71

Đối với một chỉ mục cột thực sự, nó tạo ra một chút khác biệt so với quan điểm của Trình tối ưu hóa truy vấn.

Đối với định nghĩa bảng

CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] ASC))

Truy vấn

SELECT TOP 10 *
FROM T1
ORDER BY ID DESC

Sử dụng quét theo thứ tự với hướng quét BACKWARDnhư có thể thấy trong Kế hoạch thực hiện. Có một sự khác biệt nhỏ tuy nhiên hiện tại chỉ FORWARDcó thể quét song song.

Kế hoạch

Tuy nhiên, nó có thể tạo ra một sự khác biệt lớn về sự phân mảnh hợp lý . Nếu chỉ mục được tạo với các khóa giảm dần nhưng các hàng mới được nối với các giá trị khóa tăng dần thì bạn có thể kết thúc với mọi trang theo thứ tự logic. Điều này có thể ảnh hưởng nghiêm trọng đến kích thước của IO đọc khi quét bảng và nó không có trong bộ đệm.

Xem kết quả phân mảnh

                    avg_fragmentation                    avg_fragment
name   page_count   _in_percent         fragment_count   _size_in_pages
------ ------------ ------------------- ---------------- ---------------
T1     1000         0.4                 5                200
T2     1000         99.9                1000             1

cho kịch bản dưới đây

/*Uses T1 definition from above*/
SET NOCOUNT ON;

CREATE TABLE T2( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] DESC))

BEGIN TRAN

GO
INSERT INTO T1 DEFAULT VALUES
GO 1000
INSERT INTO T2 DEFAULT VALUES
GO 1000

COMMIT

SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T1'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 
UNION ALL 
SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T2'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 

Có thể sử dụng tab kết quả không gian để xác minh giả định rằng điều này là do các trang sau có giá trị khóa tăng dần trong cả hai trường hợp.

SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T1
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
UNION ALL
SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T2
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )

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


Cảm ơn Martin vì TIP tuyệt vời này, điều này thực sự giúp tôi trong các truy vấn xếp hạng
TheGameiswar

Tôi tự hỏi nếu tôi có chỉ số giảm dần, thì hãy chọn mycolumn từ mytable trong đó indexed_column = \ @myvalue nhanh hơn khi \ @myvalue gần với giá trị tối đa có thể hơn trong trường hợp khi \ @myvalue được đóng ở giá trị tối thiểu có thể.
Lajos Arpad

@LajosArpad tại sao một người sẽ nhanh hơn? Cây B là cây cân đối. Độ sâu của cây là giống nhau cho cả hai.
Martin Smith

@MartinSmith độ sâu là như nhau, nhưng tôi nghi ngờ thứ tự của anh chị em sẽ không tạo ra sự khác biệt
Lajos Arpad

@MartinSmith, nếu thứ tự của anh chị em thậm chí có một chút khác biệt về hiệu suất, thì việc chạy hàng triệu lựa chọn sẽ tăng lên, chưa kể đến việc tham gia đa chiều.
Lajos Arpad

8

Thứ tự sắp xếp quan trọng khi bạn muốn lấy nhiều dữ liệu được sắp xếp, không phải các bản ghi riêng lẻ.

Lưu ý rằng (như bạn đang đề xuất với câu hỏi của bạn) thứ tự sắp xếp thường ít quan trọng hơn nhiều so với cột bạn đang lập chỉ mục (hệ thống có thể đọc chỉ mục ngược lại nếu thứ tự ngược lại với những gì nó muốn). Tôi hiếm khi đưa ra thứ tự sắp xếp chỉ mục bất kỳ suy nghĩ, trong khi tôi đau đớn trên các cột được bao phủ bởi chỉ mục.

@Quassnoi cung cấp một ví dụ tuyệt vời khi nó quan trọng.

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.