Làm thế nào quan trọng là thứ tự của các cột trong chỉ mục?


173

Tôi đã nghe nói rằng bạn nên đặt các cột sẽ được lựa chọn nhiều nhất khi bắt đầu khai báo chỉ mục. Thí dụ:

CREATE NONCLUSTERED INDEX MyINDX on Table1
(
   MostSelective,
   SecondMost,
   Least
)

Trước hết, những gì tôi đang nói có đúng không? Nếu vậy, tôi có thể thấy sự khác biệt lớn về hiệu suất bằng cách sắp xếp lại thứ tự các cột trong chỉ mục của tôi hay đó là một cách thực hành "tốt để làm"?

Lý do tôi hỏi là vì sau khi đặt một truy vấn thông qua DTA, tôi khuyên tôi nên tạo một chỉ mục có gần như tất cả các cột trong đó như một chỉ mục hiện có, chỉ theo một thứ tự khác. Tôi đã xem xét chỉ cần thêm các cột còn thiếu vào chỉ mục hiện có và gọi nó là tốt. Suy nghĩ?

Câu trả lời:


193

Nhìn vào một chỉ số như thế này:

Cols
  1   2   3
-------------
|   | 1 |   |
| A |---|   |
|   | 2 |   |
|---|---|   |
|   |   |   |
|   | 1 | 9 |
| B |   |   |
|   |---|   |
|   | 2 |   |
|   |---|   |
|   | 3 |   |
|---|---|   |

Xem cách hạn chế trên A trước, vì cột đầu tiên của bạn loại bỏ nhiều kết quả hơn so với hạn chế trên cột thứ hai của bạn trước? Sẽ dễ dàng hơn nếu bạn hình dung cách chỉ mục phải được duyệt qua, cột 1, rồi cột 2, v.v ... bạn thấy rằng việc bỏ qua hầu hết các kết quả trong đường chuyền sẽ giúp bước thứ 2 nhanh hơn rất nhiều.

Một trường hợp khác, nếu bạn truy vấn trên cột 3, trình tối ưu hóa thậm chí sẽ không sử dụng chỉ mục, vì nó hoàn toàn không hữu ích trong việc thu hẹp các tập kết quả. Bất cứ khi nào bạn đang truy vấn, thu hẹp số lượng kết quả để xử lý trước bước tiếp theo có nghĩa là hiệu suất tốt hơn.

Vì chỉ mục cũng được lưu trữ theo cách này, nên không có quay lại qua chỉ mục để tìm cột đầu tiên khi bạn truy vấn trên đó.

Tóm lại: Không, nó không phải để trưng bày, có những lợi ích hiệu suất thực sự.


13
Trong hình trên, hãy nhớ rằng chỉ mục đó sẽ chỉ có lợi nếu Cột 1 được chỉ định trong truy vấn. Nếu truy vấn của bạn chỉ xác định Cột 2 trong Dự đoán tham gia hoặc Tìm kiếm thì nó sẽ không có ích. Vì vậy, vấn đề đặt hàng cũng có. Có lẽ điều đó không cần phải nói, nhưng muốn đề cập đến nó.
CodeCowboyOrg

3
Ngoài ra, hãy nhớ rằng, giả sử Chỉ mục của bạn giống như hình trên và bộ lọc truy vấn của bạn trên cột1 và cột2, nhưng cột 2 độc đáo hơn và những gì bạn thực sự muốn lọc thực sự là cột 2, thì sẽ có ích hơn khi chỉ có một chỉ mục cột 2 là đầu tiên. Điều này có vẻ trái ngược nhưng hãy nhớ rằng một chỉ mục được lưu trữ trên một số trang và là một cây có một loạt các giá trị, trong khi Cột 1 ở trên phủ nhận 1/2 khả năng, chỉ mục đã biết trang chỉ mục nào sẽ đi thẳng vào Giá trị cột2, không cần cột 1 để thu hẹp tập hợp.
CodeCowboyOrg

4
Bức tranh này không phải là một đại diện chính xác về cách các chỉ mục được cấu trúc hoặc điều hướng. Đã gửi câu trả lời chỉnh sửa stackoverflow.com/a/39080819/73226
Martin Smith

6
@MartinSmith Tôi không đồng ý rằng nó không chính xác. Nó được thừa nhận cực kỳ đơn giản, đó là ý định của tôi. Tuy nhiên, câu trả lời của bạn đào sâu vào chi tiết hơn về các cấp độ được đánh giá cao, đối với những người muốn tìm hiểu sâu hơn về nó. Nếu bạn nhìn vào hình ảnh cây của bạn, bạn sẽ thấy những gì tôi đang minh họa một cách rất đơn giản. Điều này không phải là rất độc đáo hoặc thậm chí là SQL cụ thể; Lập chỉ mục cây B là khá phổ biến trên rất nhiều thứ.
Nick Craver

@MartinSmith Tôi cũng không đồng ý rằng nó không chính xác, những gì bạn đang mô tả là hành vi tiêu chuẩn về cách đưa ra chỉ số - tính chọn lọc quan trọng hơn nhiều khi bạn thực hiện các truy vấn phạm vi vì điều này giảm thiểu số lượng trang chỉ mục mà trình tối ưu hóa phải quét; điều này có thể có ý nghĩa trong các bảng lớn với hàng triệu hàng
Paul Hatcher

127

Thứ tự của các cột là rất quan trọng. Bây giờ thứ tự nào là chính xác, nó phụ thuộc vào cách bạn sẽ truy vấn nó. Một chỉ mục có thể được sử dụng để thực hiện tìm kiếm chính xác hoặc quét phạm vi. Một tìm kiếm chính xác là khi các giá trị cho tất cả các cột trong chỉ mục được chỉ định và truy vấn chính xác trên hàng được quan tâm. Để tìm kiếm thứ tự các cột không liên quan. Quét phạm vi là khi chỉ một số cột được chỉ định và trong trường hợp này khi thứ tự trở nên quan trọng. SQL Server có thể sử dụng một chỉ mục để quét phạm vi chỉ khi cột ngoài cùng bên trái được chỉ định và sau đó chỉ khi cột ngoài cùng bên trái được chỉ định, v.v. Nếu bạn có một chỉ mục trên (A, B, C), nó có thể được sử dụng để quét phạm vi A=@a, A=@a AND B=@bnhưng không phải cho B=@b, C=@ccũng không B=@b AND C=@c. Các trường hợp A=@a AND C=@clà một, như trongA=@aphần sẽ sử dụng chỉ mục, nhưng phần C=@ckhông (truy vấn sẽ quét tất cả các giá trị B cho A=@a, sẽ không 'bỏ qua' đến C=@c). Các hệ thống cơ sở dữ liệu khác có toán tử 'bỏ qua quét' có thể tận dụng một số lợi thế của các cột bên trong trong một chỉ mục khi các cột bên ngoài không được chỉ định.

Với kiến ​​thức đó trong tay, bạn có thể xem lại các định nghĩa chỉ số. Một chỉ mục trên (MostSelective, SecondMost, Least)sẽ chỉ có hiệu lực khi MostSelectivecột được chỉ định. Nhưng đó là lựa chọn nhiều nhất, sự liên quan của các cột bên trong sẽ nhanh chóng suy giảm. Rất thường xuyên bạn sẽ thấy rằng một chỉ số tốt hơn là bật (MostSelective) include (SecondMost, Least)hoặc bật (MostSelective, SecondMost) include (Least). Bởi vì các cột bên trong ít liên quan hơn, việc đặt các cột có độ chọn lọc thấp vào các vị trí bên phải như vậy trong chỉ mục sẽ khiến chúng không có gì ngoài tiếng ồn khi tìm kiếm, do đó, nên di chuyển chúng ra khỏi các trang trung gian và chỉ giữ chúng trên các trang lá truy vấn mục đích che phủ. Nói cách khác, di chuyển chúng đến INCLUDE. Điều này trở nên quan trọng hơn khi kích thước của Leastcột tăng lên. Ý tưởng là chỉ mục này chỉ có thể có lợi cho các truy vấn chỉ địnhMostSelective hoặc là một giá trị chính xác hoặc một phạm vi và cột đó là lựa chọn nhiều nhất, nó đã giới hạn các hàng ứng cử viên ở mức độ lớn.

Mặt khác, một chỉ số trên (Least, SecondMost, MostSelective)có vẻ là một sai lầm, nhưng nó thực sự là một chỉ số mạnh mẽ. Bởi vì nó có Leastcột là truy vấn ngoài cùng của nó, nó có thể được sử dụng cho các truy vấn phải tổng hợp kết quả trên các cột có độ chọn lọc thấp. Các truy vấn như vậy là phổ biến trong OLAP và kho dữ liệu phân tích, và đây chính xác là nơi các chỉ mục như vậy có một trường hợp rất tốt sẽ xảy ra với chúng. Các chỉ mục như vậy thực sự tạo ra các chỉ mục cụm tuyệt vời , chính xác vì chúng tổ chức bố trí vật lý trên các khối lớn của các hàng liên quan (cùng Leastgiá trị, thường chỉ ra một số loại hoặc loại) và chúng tạo điều kiện cho các truy vấn phân tích.

Vì vậy, thật không may, không có thứ tự 'chính xác'. Bạn không nên làm theo bất kỳ công thức cắt cookie nào mà thay vào đó hãy phân tích mẫu truy vấn bạn sẽ sử dụng theo các bảng đó và quyết định thứ tự cột chỉ mục nào là đúng.


3
Phản ứng tuyệt vời như Remus thông thường. Tôi sẽ đọc qua đoạn thứ ba của bạn một vài lần nữa và theo dõi. Tôi nghi ngờ đó có thể là chính xác những gì tôi cần làm.
Abe Miessler

"Máy chủ SQL chỉ có thể sử dụng một chỉ mục để quét phạm vi nếu cột ngoài cùng bên trái được chỉ định và sau đó chỉ khi cột ngoài cùng bên trái được chỉ định, v.v." Đây chính xác là những gì còn thiếu từ sự hiểu biết của tôi, cảm ơn! Tôi không biết quét phạm vi chỉ có thể được thực hiện trên cột chỉ mục được sử dụng ngoài cùng, nhưng bây giờ tôi thực hiện nó rất có ý nghĩa.
Allon Guralnek

Là giải thích này áp dụng cho Oracle DB?
một

1
@Roizpi Vâng, về cơ bản, bất kỳ cơ sở dữ liệu quan hệ nào với Index đều hoạt động giống nhau hoặc rất giống nhau.
Tatranskymvedved

45

Như Remus nói nó phụ thuộc vào khối lượng công việc của bạn.

Tôi muốn giải quyết một khía cạnh sai lệch của câu trả lời được chấp nhận mặc dù.

Đối với các truy vấn đang thực hiện tìm kiếm bình đẳng trên tất cả các cột trong chỉ mục, không có sự khác biệt đáng kể.

Dưới đây tạo ra hai bảng và điền chúng với dữ liệu giống hệt nhau. Sự khác biệt duy nhất là một cái có các khóa được sắp xếp từ hầu hết đến ít chọn lọc và cái còn lại thì ngược lại.

CREATE TABLE Table1(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);
CREATE TABLE Table2(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);

CREATE NONCLUSTERED INDEX MyINDX on Table1(MostSelective,SecondMost,Least);
CREATE NONCLUSTERED INDEX MyINDX2 on Table2(Least,SecondMost,MostSelective);

INSERT INTO Table1 (MostSelective, SecondMost, Least)
output inserted.* into Table2
SELECT TOP 26 REPLICATE(CHAR(number + 65),800), number/5, '~'
FROM master..spt_values
WHERE type = 'P' AND number >= 0
ORDER BY number;

Bây giờ thực hiện một truy vấn đối với cả hai bảng ...

SELECT *
FROM   Table1
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~';

SELECT *
FROM   Table2
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~'; 

... Cả hai đều sử dụng một chỉ số tốt và cả hai đều được cung cấp cùng một chi phí.

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

Nghệ thuật ASCII trong câu trả lời được chấp nhận thực tế không phải là cách các chỉ mục được cấu trúc. Các trang chỉ mục cho Bảng 1 được trình bày bên dưới (nhấp vào hình ảnh để mở ở kích thước đầy đủ).

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

Các trang chỉ mục chứa các hàng chứa toàn bộ khóa (trong trường hợp này thực sự có một cột khóa bổ sung được gắn cho mã định danh hàng vì chỉ mục không được khai báo là duy nhất nhưng có thể bỏ qua thông tin thêm về điều này có thể được tìm thấy ở đây ).

Đối với truy vấn trên, SQL Server không quan tâm đến tính chọn lọc của các cột. Nó thực hiện tìm kiếm nhị phân của trang gốc và phát hiện ra rằng Key (PPP...,3,~ )>=(JJJ...,1,~ )< (SSS...,3,~ )vì vậy nó nên đọc trang 1:118. Sau đó, nó thực hiện tìm kiếm nhị phân của các mục chính trên trang đó và định vị trang lá để di chuyển xuống.

Việc thay đổi chỉ mục theo thứ tự chọn lọc không ảnh hưởng đến số lượng so sánh chính dự kiến ​​từ tìm kiếm nhị phân hoặc số trang cần điều hướng để thực hiện tìm kiếm chỉ mục. Tốt nhất là nó có thể tăng tốc độ so sánh chính nó.

Đôi khi, việc sắp xếp chỉ mục chọn lọc nhất trước tiên sẽ có ý nghĩa đối với các truy vấn khác trong khối lượng công việc của bạn.

Ví dụ: nếu khối lượng công việc chứa các truy vấn của cả hai hình thức sau.

SELECT * ... WHERE  MostSelective = 'P'

SELECT * ...WHERE Least = '~'

Các chỉ số ở trên không bao gồm một trong hai. MostSelectiveđủ chọn lọc để thực hiện một kế hoạch với tìm kiếm và tra cứu đáng giá nhưng truy vấn Leastkhông được.

Tuy nhiên, kịch bản này (không bao gồm tìm kiếm chỉ mục trên tập hợp con của cột hàng đầu của một chỉ mục tổng hợp) chỉ là một loại truy vấn có thể có thể được trợ giúp bởi một chỉ mục. Nếu bạn không bao giờ thực sự tự mình tìm kiếm MostSelectivehoặc kết hợp MostSelective, SecondMostvà luôn luôn tìm kiếm theo sự kết hợp của cả ba cột thì lợi thế về mặt lý thuyết này là vô ích đối với bạn.

Ngược lại các truy vấn như

SELECT MostSelective,
       SecondMost,
       Least
FROM   Table2
WHERE  Least = '~'
ORDER  BY SecondMost,
          MostSelective 

Sẽ được giúp đỡ bằng cách có thứ tự ngược lại của quy định thường được quy định - vì nó bao gồm truy vấn, có thể hỗ trợ tìm kiếm và trả về các hàng theo thứ tự mong muốn để khởi động.

Vì vậy, đây là một lời khuyên thường được lặp đi lặp lại nhưng nhiều nhất nó là một câu hỏi về lợi ích tiềm năng đối với các truy vấn khác - và nó không thay thế cho việc thực sự xem xét khối lượng công việc của bạn .


31

bạn nên đặt các cột sẽ được chọn nhiều nhất khi bắt đầu khai báo chỉ mục.

Chính xác. Các chỉ mục có thể là vật liệu tổng hợp - bao gồm nhiều cột - và thứ tự rất quan trọng vì nguyên tắc ngoài cùng bên trái. Lý do là, cơ sở dữ liệu kiểm tra danh sách từ trái sang phải và phải tìm một tham chiếu cột tương ứng khớp với thứ tự được xác định. Ví dụ: có một chỉ mục trên bảng địa chỉ với các cột:

  • Địa chỉ
  • Thành phố
  • Tiểu bang

Bất kỳ truy vấn nào sử dụng addresscột đều có thể sử dụng chỉ mục, nhưng nếu truy vấn chỉ có một trong hai cityvà / hoặc statetham chiếu - thì không thể sử dụng chỉ mục. Điều này là do cột ngoài cùng bên trái không được tham chiếu. Hiệu suất truy vấn sẽ cho bạn biết cái nào là tối ưu - các chỉ mục riêng lẻ hoặc nhiều vật liệu tổng hợp với các đơn hàng khác nhau. Đọc tốt: Điểm bùng phát , bởi Kimberley Tripp


Điều gì xảy ra nếu nó chỉ là cột ngoài cùng bên phải không được sử dụng? Vì vậy, một truy vấn được sử dụng Địa chỉ và thành phố, nhưng KHÔNG nêu. Chỉ số sẽ được sử dụng sau đó?
Abe Miessler

@Abe: Cực phải sẽ không được sử dụng - bạn phải đáp ứng thứ tự chỉ mục bắt đầu từ bên trái. Bỏ lỡ một, không thể sử dụng nó.
Ngựa Non OMG

4
@Abe: Nếu bạn truy vấn Địa chỉ và thành phố, nhưng KHÔNG nêu rõ - thì có, chỉ mục sẽ được sử dụng. Nói cách khác, cơ sở dữ liệu có thể sử dụng các chỉ mục một phần để đáp ứng yêu cầu, miễn là nó có thể bắt đầu từ bên trái của một chỉ mục và di chuyển sang bên phải trong việc sử dụng các trường đang được truy vấn. Tuy nhiên, nếu bạn đã truy vấn bằng Địa chỉ và Trạng thái, nhưng KHÔNG phải thành phố, nó vẫn có thể sử dụng chỉ mục, nhưng nó sẽ không hiệu quả - bởi vì bây giờ nó chỉ có thể sử dụng phần Địa chỉ của chỉ mục (b / c tiếp theo là thành phố và nó không được sử dụng trong truy vấn).
JaredC

6

Tất cả các câu trả lời khác đều sai.

Độ chọn lọc của các cột riêng lẻ trong một chỉ mục tổng hợp không quan trọng khi chọn thứ tự.

Đây là quá trình suy nghĩ đơn giản: Thực tế , một chỉ số là sự kết hợp của các cột liên quan.

Đưa ra lý do đó, sự khác biệt duy nhất là so sánh hai "chuỗi" khác nhau sớm hơn so với sau đó trong chuỗi. Đây là một phần rất nhỏ trong tổng chi phí. Không có "vượt qua đầu tiên / lần thứ hai", như được đề cập trong một câu trả lời.

Vậy, nên sử dụng thứ tự nào?

  1. Bắt đầu với (các) cột được thử nghiệm với =, theo bất kỳ thứ tự nào .
  2. Sau đó tack trên một cột phạm vi.

Ví dụ, cột chọn lọc rất thấp phải đứng đầu trong phần này:

WHERE deleted = 0  AND  the_datetime > NOW() - INTERVAL 7 DAY
INDEX(deleted, the_datetime)

Trao đổi thứ tự trong chỉ mục sẽ hoàn toàn bỏ qua deleted.

(Có rất nhiều quy tắc hơn để đặt hàng các cột.)


Là phiếu bầu tiêu cực vì tôi sai? Hay bởi vì tôi có một quan điểm mạnh mẽ? Hay cái gì khác?
Rick James

không phải là downvote của tôi, nhưng đã xóa = 0 đối với tôi nghe có vẻ như nó không có độ chọn lọc thấp? Tôi tưởng tượng nó sẽ là phần lớn các hàng trong bảng.
Greg

@Greg - Tôi nghĩ điều đó có nghĩa là "tính chọn lọc thấp" - Nghĩa là, việc sử dụng deletedkhông giúp ích nhiều trong việc lọc ra các hàng không mong muốn. Bạn có một ví dụ tốt hơn? (Đó là một trong những điều xuất hiện trong tâm trí của tôi khi tôi viết Câu trả lời.)
Rick James

Hiểu lầm về phía tôi.
Greg

1
@ClickOk - Cảm ơn. Sách dạy nấu ăn của tôi cung cấp một số thông tin cơ bản: mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James
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.