Phiên bản ngắn: tìm kiếm tốt hơn nhiều
Phiên bản ngắn hơn: tìm kiếm thường tốt hơn nhiều, nhưng rất nhiều tìm kiếm (gây ra bởi thiết kế truy vấn xấu với các truy vấn phụ tương quan khó chịu hoặc do bạn đang thực hiện nhiều truy vấn trong thao tác con trỏ hoặc vòng lặp khác) có thể tệ hơn một quét, đặc biệt nếu truy vấn của bạn có thể sẽ trả về dữ liệu từ hầu hết các hàng trong bảng bị ảnh hưởng.
Nó giúp bao quát cả gia đình cho các hoạt động tìm kiếm dữ liệu để hiểu đầy đủ ý nghĩa hiệu suất.
Quét bảng: Không có chỉ mục nào liên quan đến truy vấn của bạn, trình hoạch định buộc phải sử dụng quét bảng có nghĩa là mọi hàng được xem xét. Điều này có thể dẫn đến mọi trang liên quan đến dữ liệu của bảng được đọc từ đĩa thường là trường hợp xấu nhất. Lưu ý rằng đối với một số truy vấn, nó sẽ sử dụng quét bảng ngay cả khi có chỉ mục hữu ích - điều này thường là do dữ liệu trong bảng quá nhỏ nên sẽ gặp nhiều rắc rối hơn khi đi qua các chỉ mục (nếu đây là trường hợp bạn mong đợi có kế hoạch thay đổi khi dữ liệu tăng lên, giả sử thước đo chọn lọc của chỉ số là tốt).
Quét chỉ mục với tra cứu hàng: Không tìm thấy chỉ mục nào có thể được sử dụng trực tiếp cho tìm kiếm nhưng chỉ mục chứa các cột bên phải sẽ xuất hiện quét chỉ mục. Ví dụ: nếu bạn có một bảng lớn có 20 cột với chỉ mục trên cột1, col2, col3 và bạn phát hành SELECT col4 FROM exampletable WHERE col2=616
, trong trường hợp này, quét chỉ mục để truy vấn col2
sẽ tốt hơn quét toàn bộ bảng. Khi các hàng khớp được tìm thấy thì các trang dữ liệu cần được đọc để lấy col4 cho đầu ra (hoặc tham gia thêm), đó là giai đoạn "tra cứu dấu trang" khi bạn nhìn thấy nó trong các kế hoạch truy vấn.
Quét chỉ mục mà không cần tra cứu hàng: Nếu ví dụ trên SELECT col1, col2, col3 FROM exampletable WHERE col2=616
là không cần nỗ lực thêm để đọc các trang dữ liệu: một khi col2=616
tìm thấy các hàng chỉ mục phù hợp với tất cả các dữ liệu được yêu cầu. Đây là lý do tại sao đôi khi bạn thấy các cột sẽ không bao giờ được tìm kiếm, nhưng có khả năng được yêu cầu đầu ra, được thêm vào cuối chỉ mục - nó có thể lưu tra cứu hàng. Khi thêm các cột vào một chỉ mục vì lý do này và chỉ vì lý do này, hãy thêm chúng vào INCLUDE
mệnh đề để nói với công cụ rằng nó không cần tối ưu hóa bố cục chỉ mục để truy vấn dựa trên các cột này (điều này có thể tăng tốc các cập nhật được thực hiện cho các cột đó) . Quét chỉ mục có thể là kết quả của các truy vấn không có mệnh đề lọc: SELECT col2 FROM exampletable
sẽ quét chỉ mục ví dụ này thay vì các trang bảng.
Tìm kiếm chỉ mục (có hoặc không có tra cứu hàng) : Trong tìm kiếm, không phải tất cả các chỉ mục đều được xem xét. Đối với truy SELECT * FROM exampletable WHERE c1 BETWEEN 1234 AND 4567
vấn, công cụ truy vấn có thể tìm thấy hàng đầu tiên sẽ khớp bằng cách thực hiện tìm kiếm dựa trên cây trên chỉ mục trên c1
đó sau đó nó có thể điều hướng chỉ mục theo thứ tự cho đến khi đến cuối phạm vi (điều này giống với truy vấn cho c1=1234
là có thể có nhiều hàng phù hợp với điều kiện ngay cả đối với một =
hoạt động). Điều này có nghĩa là chỉ cần đọc các trang chỉ mục có liên quan (cộng với một vài trang cần thiết cho tìm kiếm ban đầu) thay vì mỗi trang trong chỉ mục (hoặc bảng).
Các chỉ mục được nhóm: Với một chỉ mục được nhóm, dữ liệu bảng được lưu trữ trong các nút lá của chỉ mục đó thay vì nằm trong một cấu trúc heap riêng. Điều này có nghĩa là sẽ không bao giờ cần phải có thêm bất kỳ tra cứu hàng nào sau khi tìm các hàng bằng chỉ mục đó bất kể cột nào là cần thiết [trừ khi bạn có dữ liệu ngoài trang như TEXT
cột hoặc VARCHAR(MAX)
cột chứa dữ liệu dài].
Bạn chỉ có thể có một chỉ mục được nhóm vì lý do này [1] , chỉ mục được nhóm là bảng của bạn thay vì có cấu trúc heap riêng, vì vậy nếu bạn sử dụng một [2], hãy chọn nơi bạn đặt nó cẩn thận để đạt được mức tăng tối đa.
Cũng lưu ý rằng chỉ mục được phân cụm vì "khóa phân cụm" cho bảng và được bao gồm trong mọi chỉ mục không phân cụm trên bảng, do đó, một chỉ mục phân cụm rộng thường không phải là một ý tưởng hay.
[1] Trên thực tế, bạn có thể có nhiều chỉ mục được phân cụm một cách hiệu quả bằng cách xác định các chỉ mục không phân cụm bao gồm hoặc bao gồm mọi cột trên bảng, nhưng điều này có thể gây lãng phí không gian có tác động hiệu suất ghi vì vậy nếu bạn cân nhắc thực hiện thì hãy đảm bảo bạn thực sự cần
[2] Khi tôi nói "nếu bạn sử dụng một chỉ mục được nhóm", xin lưu ý rằng thông thường bạn nên có một bảng trên mỗi bảng. Có các trường hợp ngoại lệ như với tất cả các quy tắc ngón tay cái, các bảng chỉ nhìn thấy ít hơn là chèn số lượng lớn và đọc không theo thứ tự (bảng phân tầng cho các quy trình ETL có lẽ) là ví dụ phổ biến nhất.
Điểm bổ sung: Quét chưa hoàn thành:
Điều quan trọng cần nhớ là tùy thuộc vào phần còn lại của truy vấn, quét bảng / chỉ mục có thể không thực sự quét toàn bộ bảng - nếu logic cho phép kế hoạch truy vấn có thể khiến nó hủy bỏ sớm. Ví dụ đơn giản nhất về điều này là SELECT TOP(1) * FROM HugeTable
- nếu bạn nhìn vào kế hoạch truy vấn, bạn sẽ thấy rằng chỉ có một hàng được trả về từ quá trình quét và nếu bạn xem số liệu thống kê IO ( SET STATISTICS IO ON; SELECT TOP(1) * FROM HugeTable
) bạn sẽ thấy rằng nó chỉ đọc một số rất nhỏ của các trang (có lẽ chỉ là một).
Điều tương tự có thể xảy ra nếu vị từ của mệnh đề WHERE
hoặc JOIN ... ON
mệnh đề có thể được chạy đồng thời với quá trình quét là nguồn nếu dữ liệu của nó. Trình lập kế hoạch truy vấn / người chạy đôi khi có thể rất thông minh về việc đẩy các vị từ quay trở lại các nguồn dữ liệu để cho phép chấm dứt sớm các lần quét theo cách này (và đôi khi bạn có thể khéo léo sắp xếp lại các truy vấn để giúp thực hiện điều đó!). Mặc dù dữ liệu chảy từ phải sang trái theo các mũi tên trong màn hình kế hoạch truy vấn tiêu chuẩn, logic chạy từ trái sang phải và mỗi bước (từ phải sang trái) không nhất thiết phải chạy để hoàn thành trước khi bước tiếp theo có thể bắt đầu. Trong ví dụ đơn giản ở trên nếu bạn xem từng khối trong kế hoạch truy vấn như một tác nhân, SELECT
tác nhân sẽ hỏi TOP
tác nhân đó một hàng, lần lượt hỏiTABLE SCAN
Đại lý cho một, sau đó SELECT
đại lý yêu cầu một đại lý khác nhưng TOP
đại lý biết rằng không cần phải không hỏi người đọc bảng, SELECT
đại lý nhận được phản hồi "không còn phù hợp" và biết tất cả công việc đã được thực hiện. Nhiều hoạt động chặn loại này tối ưu hóa các quá trình như vậy thường trong các ví dụ phức tạp hơn một bảng / index quét thực sự không đọc từng hàng, nhưng phải cẩn thận không để nhảy đến kết luận rằng bất kỳ quét phải là một hoạt động tốn kém.