Tại sao truy vấn này không sử dụng chỉ mục không bao gồm của tôi và làm cách nào tôi có thể thực hiện?


12

Theo câu hỏi này về việc tăng hiệu suất truy vấn, tôi muốn biết liệu có cách nào để làm cho chỉ mục của tôi được sử dụng theo mặc định hay không.

Truy vấn này chạy trong khoảng 2,5 giây:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

Cái này chạy trong khoảng 33ms:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31' 
ORDER BY [DateEntered], [DeviceID];

Có một chỉ mục được nhóm trên trường [ID] (pk) và có một chỉ mục không được nhóm trên [Date Entryed], [DeviceID]. Truy vấn đầu tiên sử dụng chỉ mục được phân cụm, truy vấn thứ hai sử dụng chỉ mục không phân cụm của tôi. Câu hỏi của tôi là hai phần:

  • Tại sao, vì cả hai truy vấn đều có mệnh đề WHERE trên trường [Date Entryed], nên máy chủ có sử dụng chỉ mục cụm trên đầu tiên, nhưng không phải là thứ hai không?
  • Làm cách nào tôi có thể làm cho chỉ mục không được phân cụm được sử dụng theo mặc định trên truy vấn này ngay cả khi không có thứ tự? (Hoặc tại sao tôi không muốn hành vi đó?)

Date Entryed là DateTime, trong trường hợp này tôi đang sử dụng phần ngày, nhưng đôi khi tôi truy vấn cả ngày và thời gian cùng nhau.
Nate

Câu trả lời:


9

truy vấn đầu tiên thực hiện quét bảng dựa trên ngưỡng tôi đã giải thích trước đó: Có thể tăng hiệu suất truy vấn trên một bảng hẹp với hàng triệu hàng không?

(rất có thể truy vấn của bạn không có TOP 1000mệnh đề sẽ trả về hơn 46k hàng hoặc một số trong khoảng từ 35k đến 46k. (vùng màu xám ;-))

truy vấn thứ hai, phải được đặt hàng. Vì chỉ mục NC của bạn được sắp xếp theo thứ tự bạn muốn, nên trình tối ưu hóa sẽ sử dụng chỉ mục đó rẻ hơn, sau đó đến phần tra cứu dấu trang đến chỉ mục được nhóm để lấy các cột bị thiếu khi thực hiện quét chỉ mục cụm và sau đó cần quét để đặt hàng đó.

đảo ngược thứ tự của các cột trong ORDER BYmệnh đề và bạn quay lại quét chỉ mục theo cụm vì NC INDEX sau đó vô dụng.

chỉnh sửa quên câu trả lời cho câu hỏi thứ hai của bạn, tại sao bạn KHÔNG muốn điều này

Sử dụng một chỉ mục không bao gồm cụm không có nghĩa là một hàngID được tra cứu trong chỉ mục NC và sau đó các cột bị thiếu phải được tra cứu trong chỉ mục được phân cụm (chỉ mục được nhóm chứa tất cả các cột của bảng). IO để tra cứu các cột bị thiếu trong chỉ mục được nhóm là IO ngẫu nhiên.

Chìa khóa ở đây là RANDOM. bởi vì đối với mỗi hàng được tìm thấy trong chỉ mục NC, các phương thức truy cập phải tìm kiếm một trang mới trong chỉ mục được nhóm. Điều này là ngẫu nhiên, và do đó rất tốn kém.

Bây giờ, mặt khác, trình tối ưu hóa cũng có thể thực hiện quét chỉ mục cụm. Nó có thể sử dụng bản đồ phân bổ để tra cứu phạm vi quét và chỉ cần bắt đầu đọc chỉ mục Clustered trong các khối lớn. Đây là tuần tự và rẻ hơn nhiều. (miễn là bảng của bạn không bị phân mảnh :-)) Nhược điểm là, chỉ số cụm WHOLE cần được đọc. Điều này không tốt cho bộ đệm của bạn và có khả năng là một số lượng lớn IOs. nhưng vẫn còn, các IO liên tiếp.

Trong trường hợp của bạn, trình tối ưu hóa quyết định ở đâu đó giữa các hàng 35k và 46k, sẽ ít tốn kém hơn khi quét chỉ mục toàn cụm. Vâng, đó là sai. Và trong rất nhiều trường hợp với các chỉ mục không được thu hẹp mà không chọn WHEREcác mệnh đề hoặc bảng lớn cho vấn đề này, điều này đã sai. (Bảng của bạn tệ hơn, vì đó cũng là một bảng rất hẹp.)

Bây giờ, việc thêm ORDER BYlàm cho tốn kém hơn để quét chỉ mục cụm đầy đủ và sau đó đặt hàng kết quả. Thay vào đó, trình tối ưu hóa giả định sẽ rẻ hơn khi sử dụng chỉ số NC đã đặt hàng và sau đó trả tiền phạt IO ngẫu nhiên cho việc tra cứu dấu trang.

Vì vậy, đơn đặt hàng của bạn là một loại giải pháp "gợi ý truy vấn" hoàn hảo. NHƯNG, tại một thời điểm nhất định, một khi kết quả truy vấn của bạn quá lớn, hình phạt cho các IO ngẫu nhiên tra cứu dấu trang sẽ rất lớn nên nó trở nên chậm hơn. Tôi giả sử trình tối ưu hóa sẽ thay đổi kế hoạch trở lại quét chỉ mục cụm trước thời điểm đó nhưng bạn không bao giờ biết chắc chắn.

Trong trường hợp của bạn, miễn là các phần chèn của bạn được sắp xếp theo enterdate, như được thảo luận trong trò chuyện và câu hỏi trước đó (xem liên kết), bạn nên tạo chỉ mục được nhóm trên cột enterDate.


20

Thể hiện truy vấn bằng cách sử dụng cú pháp khác nhau đôi khi có thể giúp truyền đạt mong muốn của bạn để sử dụng một chỉ mục không được nhóm đến trình tối ưu hóa. Bạn nên tìm mẫu dưới đây cung cấp cho bạn kế hoạch bạn muốn:

SELECT
    [ID],
    [DeviceID],
    [IsPUp],
    [IsWebUp],
    [IsPingUp],
    [DateEntered]
FROM [dbo].[Heartbeats]
WHERE
    [ID] IN
(
    -- Keys
    SELECT TOP (1000)
        [ID]
    FROM [dbo].[Heartbeats]
    WHERE 
        [DateEntered] >= CONVERT(datetime, '2011-08-30', 121)
        AND [DateEntered]  < CONVERT(datetime, '2011-08-31', 121)
);

Kế hoạch truy vấn

So sánh kế hoạch đó với kế hoạch được tạo ra khi chỉ số không phân cụm bị buộc với một gợi ý:

SELECT TOP (1000) 
    * 
FROM [dbo].[Heartbeats] WITH (INDEX(CommonQueryIndex))
WHERE 
    [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

Kế hoạch cưỡng bức chỉ số cưỡng bức

Các kế hoạch về cơ bản là giống nhau (Tra cứu khóa không có gì khác hơn là tìm kiếm trên chỉ mục được nhóm). Cả hai hình thức kế hoạch sẽ chỉ thực hiện một tìm kiếm trên chỉ mục không được nhóm và tối đa 1000 lần tra cứu vào chỉ mục được nhóm.

Sự khác biệt quan trọng là ở vị trí của nhà điều hành hàng đầu. Được định vị giữa hai lần tìm kiếm, Top ngăn chặn trình tối ưu hóa thay thế hai thao tác tìm kiếm bằng quét tương đương logic của chỉ mục được nhóm. Trình tối ưu hóa hoạt động bằng cách thay thế các phần của kế hoạch logic bằng các hoạt động quan hệ tương đương. Top không phải là toán tử quan hệ, do đó việc viết lại ngăn cản việc chuyển đổi sang quét chỉ mục cụm. Nếu trình tối ưu hóa có thể định vị lại toán tử Top, nó vẫn thích quét qua tìm kiếm + tra cứu vì cách ước tính chi phí hoạt động.

Chi phí quét và tìm kiếm

Ở mức rất cao, mô hình chi phí của trình tối ưu hóa để quét và tìm kiếm khá đơn giản: ước tính 320 lượt tìm kiếm ngẫu nhiên có chi phí tương đương với việc đọc 1350 trang trong một lần quét. Điều này có thể có chút giống với khả năng phần cứng của bất kỳ hệ thống I / O hiện đại cụ thể nào, nhưng nó hoạt động khá tốt như một mô hình thực tế.

Mô hình này cũng đưa ra một số giả định đơn giản hóa, một giả định chính là mọi truy vấn được giả sử bắt đầu mà không có trang dữ liệu hoặc chỉ mục nào trong bộ đệm. Hàm ý là mọi I / O sẽ dẫn đến I / O vật lý - mặc dù điều này hiếm khi xảy ra trong thực tế. Ngay cả với bộ đệm lạnh, việc tìm nạp trước và đọc trước có nghĩa là các trang cần thiết thực sự có khả năng nằm trong bộ nhớ vào thời điểm bộ xử lý truy vấn cần chúng.

Một xem xét khác là yêu cầu đầu tiên cho một hàng không có trong bộ nhớ sẽ khiến toàn bộ trang được tìm nạp từ đĩa. Các yêu cầu tiếp theo cho các hàng trên cùng một trang sẽ rất có thể không phát sinh I / O vật lý. Mô hình chi phí có chứa logic để tính đến một số hiệu ứng như thế này, nhưng nó không hoàn hảo.

Tất cả những điều này (và hơn thế nữa) có nghĩa là trình tối ưu hóa có xu hướng chuyển sang quét sớm hơn có thể nên. I / O ngẫu nhiên chỉ 'đắt hơn nhiều' so với 'I / O' tuần tự nếu kết quả hoạt động vật lý - truy cập các trang trong bộ nhớ thực sự rất nhanh. Ngay cả khi yêu cầu đọc vật lý, việc quét có thể không dẫn đến việc đọc tuần tự hoàn toàn do phân mảnh và tìm kiếm có thể được sắp xếp sao cho mẫu đó về cơ bản là tuần tự. Thêm vào đó là đặc tính hiệu suất thay đổi của các hệ thống I / O hiện đại (đặc biệt là trạng thái rắn) và toàn bộ mọi thứ bắt đầu trông rất run rẩy.

Mục tiêu hàng

Sự hiện diện của một nhà điều hành hàng đầu trong một kế hoạch sửa đổi cách tiếp cận chi phí. Trình tối ưu hóa đủ thông minh để biết rằng việc tìm 1000 hàng bằng cách quét có thể sẽ không yêu cầu quét toàn bộ chỉ mục cụm - nó có thể dừng ngay khi tìm thấy 1000 hàng. Nó đặt 'mục tiêu hàng' gồm 1000 hàng tại toán tử Hàng đầu và sử dụng thông tin thống kê để hoạt động trở lại từ đó để ước tính số lượng hàng mà nó cần từ nguồn hàng (quét trong trường hợp này). Tôi đã viết về các chi tiết của tính toán này ở đây .

Các hình ảnh trong câu trả lời này được tạo bằng SQL Sentry Plan Explorer .

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.