Tại sao chỉ mục của tôi có thể tìm kiếm ước tính số lượng hàng phù hợp và toán tử sắp xếp không thể?


11

Tôi có một truy vấn sử dụng một hàm trên vị ngữ, đại loại như thế này:

commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)

Tôi có một chỉ mục được lọc trên commentType có 40K hàng và khi tôi chạy truy vấn, số lượng hàng ước tính cho Index Seek là rất chính xác (khoảng 11K), nhưng đối với bước tiếp theo (toán tử sắp xếp), nó hoàn toàn bỏ qua các thống kê và chỉ ước tính tổng số hàng trong chỉ mục được lọc.

Tại sao chuyện này đang xảy ra? Tôi biết những điều cơ bản về tính khả dụng , và tôi đã thử nghiệm chỉ vì mục đích tỉnh táo thay thế dữ liệu bằng một ngày thực tế (2014-01-01) và voila ... Việc sắp xếp bắt đầu đoán chính xác số lượng hàng ...

Tại sao điều này xảy ra và làm thế nào tôi có thể sửa chữa nó? Tôi không thể vượt qua một ngày cố định ...


DATEADD(month,datediff(month,0,getdate()) - 13,0)không có ý nghĩa với tôi. Bạn đang cố gắng làm gì với điều này? Nó có thể được cải thiện / đơn giản hóa?
Daniel Hutmacher

2
@Daniel Đó là đầu tháng, 13 tháng trước.
Aaron Bertrand

1
Ngoài ra, vui lòng chỉnh sửa câu hỏi của bạn để phản ánh phiên bản SQL Server (?) Bạn đang bật. Sử dụng thẻ cho điều đó.
Daniel Hutmacher

Bạn có thể thử DATEADD(month, -13, DATEADD(day, 1-DATEPART(day, SYSDATETIME()))và xem nếu có sự khác biệt?
Daniel Hutmacher

Nếu bạn có một chỉ mục không được lọc trên (commentType, commentDate), nó có hoạt động tốt hơn ở đó không? Chỉ là các chỉ mục được lọc đôi khi có thể báo cáo sai các ước tính tại các điểm khác nhau trong các kế hoạch. Ước tính dường như thoát ra bằng cách báo cáo tổng số trong chỉ mục được lọc, nhưng thực tế là kế hoạch đang được hiển thị sai.
Rob Farley

Câu trả lời:


9

Tôi tin rằng ước tính của bạn sai vì lỗi ước tính hoán đổi hai trong số các đối số DATEDIFF. Tôi nói về điều này ở đây:

Cách giải quyết là tính ngày đầu tiên của 13 tháng trước mà không sử dụng DATEDIFF (2008+):

DATEADD(MONTH, -13, DATEADD(DAY, 1-DATEPART(DAY,GETDATE()), CONVERT(DATE, GETDATE()));

Tôi không tích cực sẽ giải quyết ước tính (Tôi đã thử nghiệm với các chỉ mục được lọc và tôi không chắc loại này thực sự đang làm gì hoặc tại sao nó có ước tính khác mà không có kế hoạch và / hoặc phần còn lại của truy vấn ).

Cách khắc phục mà Microsoft khuyến nghị là sử dụng TF 4199, nhưng tôi không chắc đó là điều bạn sẽ cần làm ở đây:

Một tùy chọn khác là đảm bảo bạn đang sử dụng SP / CU mới nhất tuyệt đối cho bất kỳ phiên bản SQL Server nào bạn đang sử dụng, vì họ cho rằng nó đã được sửa trong bài viết KB sau (mặc dù điều này vẫn sẽ yêu cầu sử dụng TF 4199 trừ khi bạn vào năm 2014 hoặc tốt hơn):

Các sửa chữa có thể thu được với các bản dựng sau:

  • 2005 SP3 CU 15 (> = 9.00.4325 VÀ <= 9.00.4999)
  • 2005 SP4 CU 2 (> = 9.00.5259)
  • 2008 SP1 CU 13 (> = 10,00.2816,00 VÀ <= 10,00.3999)
  • 2008 SP2 CU 3 (> = 10,00.4279,00 VÀ <= 10,00.5499)
  • Theo tiện ích mở rộng 2008 SP3 & SP4 (> = 10,00.5500)
  • 2008 R2 CU 7 (10.50.1777.0)
  • 2008 R2 SP1 CU 3 (> = 10.50.2769.0 VÀ <= 10.50.3999)
  • Theo tiện ích mở rộng 2008 R2 SP2 & SP3 (> = 10.50.4000)
  • Theo tiện ích mở rộng 2012, 2014, 2016 (> = 11.0)

(Lần tới, vui lòng bao gồm kết quả SELECT @@VERSIONtrong câu hỏi của bạn.)

Tôi sẽ lưu ý rằng bài viết KB nói rằng DATEDIFF có thể đánh giá thấp số lượng hàng, điều này trái ngược với những gì đang xảy ra trong kịch bản của bạn. Điều đó không có nghĩa là các bản sửa lỗi không áp dụng cho bạn; Tôi nghĩ rằng từ ngữ bài viết KB là không chính xác, vì các ước tính có thể đi theo bất kỳ cách nào tùy thuộc vào dữ liệu và phạm vi bạn đang xem.

Bài đăng trên blog của tôi ở trên đã xác nhận rằng việc hoán đổi không còn xảy ra vào năm 2014 trở lên. Để an toàn, tôi có lẽ chỉ cần loại bỏ DATEDIFF khỏi vị ngữ của bạn và sử dụng một phương pháp khác để tính toán bắt đầu phạm vi của bạn. Tôi không đề xuất mức độ quá mức của 4199 hoặc sử dụng SQL động để ngăn việc hoán đổi xấu.


Cảm ơn đã giúp đỡ ! Tôi đã thử đề nghị của bạn và kế hoạch thay đổi. Đây là cách nó đã được trước đó: s16.postimg.org/t5j6o1yed/fix_wrong.png Đây là cách nó là sau khi tôi thay đổi datediff của tôi bằng cách của bạn: postimg.org/image/5f725rj83 Tôi sẽ đọc tất cả các url bạn đã cho tôi . Chúc mừng.
MrKudz
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.