2009-04-13 47 views
102

Khi bạn tạo 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 lựa chọn này thậm chí còn ở đây. Sử dụng kỹ thuật sắp xếp nhị phân, sẽ không phải là một tra cứu được chỉ là nhanh chóng một trong hai cách? Sự khác biệt nào tạo ra thứ tự tôi chọn?Chỉ mục SQL Server - tăng dần hoặc giảm dần, nó tạo ra sự khác biệt nào?

Trả lời

105

này chủ yếu quan trọng khi sử dụng với chỉ số tổng hợp:

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

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

SELECT * 
FROM mytable 
ORDER BY 
     col1, col2 DESC 

hay:

SELECT * 
FROM mytable 
ORDER BY 
     col1 DESC, col2 

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

SELECT * 
FROM mytable 
ORDER BY 
     col1, col2 

Chỉ mục trên một cột có thể được sử dụng 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ỉ số cột duy nhất, mặc dù nó không phải rất 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 nhóm:

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

Chỉ số trên col1 tiếp tục ra lệnh của col1 cùng với các tài liệu tham khảo để hàng.

Vì bảng được nhóm lại, tham chiếu đến các hàng thực sự là các giá trị của pk. Chúng cũng được đặt trong mỗi giá trị col1.

Điều này có nghĩa rằng lá của chỉ số đang thực sự đặt trên (col1, pk), và truy vấn này:

SELECT col1, pk 
FROM mytable 
ORDER BY 
     col1, pk 

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

Nếu chúng ta tạo ra các chỉ số như sau:

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC) 

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

Điều này có nghĩa rằng các truy vấn sau đây:

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

có thể được phục vụ bởi ix_mytable_col1_desc như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 INDEX trên bất kỳ bảng nào luôn là các cột cuối của bất kỳ chỉ mục nào khác trên bảng đó.

+0

Khi bạn nói "không cho ..." làm bạn có nghĩa là nó sẽ không làm việc hoặc thực hiện sẽ là khủng khiếp? –

+2

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, tất nhiên, nhưng hiệu năng sẽ kém. – Quassnoi

+0

Trong phần đầu tiên, không nên ví dụ thứ hai nói "ORDER BY col1 DESC, col2 DESC"? –

8

Thứ tự sắp xếp quan trọng khi bạn muốn truy xuất nhiều dữ liệu được sắp xếp, chứ không phải 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 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 với thứ bạn muốn). Tôi hiếm khi đưa ra thứ tự sắp xếp chỉ mục bất kỳ suy nghĩ nào, trong khi tôi khổ sở trên các cột được chỉ số bao phủ.

@Quassnoi cung cấp số great example khi nó không vấn đề.

53

Đối với chỉ mục cột đơn thực sự, nó tạo ra sự khác biệt nhỏ 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)) 

Các Query

SELECT TOP 10 * 
FROM T1 
ORDER BY ID DESC 

Sử dụng một quét ra lệnh với quét hướng BACKWARD như có thể thấy trong Kế hoạch thực hiện. Tuy nhiên, có một chút khác biệt trong đó hiện tại chỉ có thể quét song song FORWARD.

Plan

Tuy nhiên nó có thể tạo sự khác biệt lớn về sự phân mảnh logic. Nếu chỉ mục được tạo bằng các phím giảm dần nhưng các hàng mới được nối thêm 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 tình trạng manh mún quả

    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ả thiết rằng điều này là do các trang sau đã tăng dần giá trị quan trọng trong việc 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 %%) 

enter image description here

+0

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

+0

Tôi tự hỏi liệu tôi có chỉ số giảm dần hay không, sau đó chọn mycolumn từ mytable nơi indexed_column = \ @myvalue nhanh hơn khi \ @myvalue gần với giá trị tối đa có thể so với trường hợp khi \ @myvalue bị đóng với giá trị tối thiểu có thể. –

+0

@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à như nhau cho cả hai. –

Các vấn đề liên quan