Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Trường hợp con cá trích đỏ ước tính hồng y

Bạn đang làm việc với một nhà phát triển đang báo cáo hiệu suất chậm cho lệnh gọi thủ tục được lưu trữ sau:

EXEC [dbo].[charge_by_date] '2/28/2013';

Bạn hỏi nhà phát triển đang gặp vấn đề gì, nhưng thông tin bổ sung duy nhất bạn nhận được là nó "chạy chậm". Vì vậy, bạn nhảy vào phiên bản SQL Server và xem xét thực tế kế hoạch thực hiện. Bạn làm điều này vì bạn quan tâm đến không chỉ kế hoạch thực thi trông như thế nào mà còn cả số hàng ước tính so với thực tế của kế hoạch:

Đầu tiên chỉ nhìn vào các nhà khai thác gói, bạn có thể thấy một số chi tiết đáng chú ý:

  • Có một cảnh báo trong toán tử gốc
  • Có một bản quét bảng cho cả hai bảng được tham chiếu ở cấp độ lá (charge_jan và charge_feb) và bạn thắc mắc tại sao cả hai vẫn là đống và không có chỉ mục được nhóm
  • Bạn thấy rằng chỉ có các hàng chạy qua bảng charge_feb chứ không phải bảng charge_jan
  • Bạn thấy các khu vực song song trong kế hoạch

Đối với cảnh báo trong trình lặp gốc, bạn di chuột qua nó và thấy rằng có các cảnh báo chỉ mục bị thiếu với đề xuất cho các chỉ mục sau:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[charge_feb] ([charge_dt])
INCLUDE ([charge_no])
GO
 
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[charge_jan] ([charge_dt])
INCLUDE ([charge_no])
GO

Bạn hỏi nhà phát triển cơ sở dữ liệu ban đầu tại sao không có chỉ mục nhóm và câu trả lời là “Tôi không biết.”

Tiếp tục điều tra trước khi thực hiện bất kỳ thay đổi nào, bạn nhìn vào tab Cây kế hoạch trong SQL Sentry Plan Explorer và bạn thực sự thấy rằng có sự sai lệch đáng kể giữa các hàng ước tính so với thực tế cho một trong các bảng:

Dường như có hai vấn đề:

  • Ước tính thấp hơn cho các hàng trong quá trình quét bảng charge_jan
  • Ước tính vượt mức cho các hàng trong quá trình quét bảng charge_feb

Vì vậy, các ước tính về bản số lệch, và bạn tự hỏi liệu điều này có liên quan đến việc đánh hơi tham số hay không. Bạn quyết định kiểm tra giá trị đã biên dịch của tham số và so sánh nó với giá trị thời gian chạy của tham số mà bạn có thể thấy trên tab Tham số:

Thật vậy, có sự khác biệt giữa giá trị thời gian chạy và giá trị đã biên dịch. Bạn sao chép qua cơ sở dữ liệu vào một môi trường thử nghiệm giống như sản phẩm và sau đó kiểm tra việc thực thi thủ tục được lưu trữ với giá trị thời gian chạy là 28/2/2013 trước và sau đó là 1/31/2013.

Các kế hoạch 28/2/2013 và 1/3/2013 có hình dạng giống hệt nhau nhưng luồng dữ liệu thực tế khác nhau. Kế hoạch 2/28/2013 và ước tính về số lượng như sau:

Và trong khi kế hoạch 2/28/2013 không có vấn đề gì về ước tính, thì kế hoạch 1/31/2013 thực hiện:

Vì vậy, kế hoạch thứ hai hiển thị cùng một ước tính vượt và thấp, chỉ khác với kế hoạch ban đầu mà bạn đã xem xét.

Bạn quyết định thêm các chỉ mục được đề xuất vào môi trường thử nghiệm giống sản phẩm cho cả bảng charge_jan và charge_feb và xem điều đó có giúp ích gì không. Thực hiện các thủ tục được lưu trữ theo thứ tự tháng 1 / tháng 2, bạn sẽ thấy các hình dạng kế hoạch mới sau đây và các ước tính về số lượng liên quan:

Kế hoạch mới sử dụng thao tác Tìm kiếm chỉ mục từ mỗi bảng, nhưng bạn vẫn thấy không có hàng nào chảy từ bảng này chứ không phải từ bảng khác và bạn vẫn thấy sai lệch ước tính số lượng dựa trên đánh giá tham số khi giá trị thời gian chạy ở một tháng khác với trình biên dịch giá trị thời gian.

Nhóm của bạn có chính sách không thêm chỉ mục mà không có bằng chứng về lợi ích đầy đủ và thử nghiệm hồi quy liên quan. Hiện tại, bạn quyết định xóa các chỉ mục không hợp nhất mà bạn vừa tạo. Trong khi bạn không giải quyết ngay lập tức cụm bị thiếu chỉ mục, bạn quyết định bạn sẽ chăm sóc nó sau.

Tại thời điểm này, bạn nhận ra rằng bạn cần phải xem xét thêm định nghĩa thủ tục được lưu trữ, như sau:

CREATE PROCEDURE dbo.charge_by_date
  @charge_dt datetime
AS
  SELECT charge_no
  FROM dbo.charge_view
  WHERE charge_dt = @charge_dt
GO

Tiếp theo, bạn xem định nghĩa đối tượng charge_view:

CREATE VIEW charge_view
AS
  SELECT *
  FROM [charge_jan]
  UNION ALL
  SELECT *
  FROM [charge_feb]
GO

Chế độ xem tham chiếu dữ liệu tính phí được phân tách thành các bảng khác nhau theo ngày. Và sau đó bạn tự hỏi liệu có thể ngăn chặn sự lệch kế hoạch thực thi truy vấn thứ hai thông qua việc thay đổi định nghĩa thủ tục được lưu trữ hay không.

Có lẽ nếu trong thời gian chạy trình tối ưu hóa biết giá trị là bao nhiêu, thì vấn đề ước tính bản số sẽ biến mất và cải thiện hiệu suất tổng thể?

Bạn tiếp tục và xác định lại lệnh gọi thủ tục được lưu trữ như sau, thêm gợi ý RECOMPILE (biết rằng bạn cũng đã nghe nói rằng điều này có thể làm tăng mức sử dụng CPU, nhưng vì đây là môi trường thử nghiệm, bạn cảm thấy an toàn khi thử):

ALTER PROCEDURE charge_by_date
  @charge_dt datetime
AS
  SELECT charge_no
  FROM dbo.charge_view
  WHERE charge_dt = @charge_dt
  OPTION (RECOMPILE);
GO

Sau đó, bạn thực hiện lại quy trình đã lưu trữ bằng cách sử dụng giá trị 1/31/2013 và sau đó là giá trị 28/2/2013.

Hình dạng kế hoạch vẫn giữ nguyên, nhưng bây giờ vấn đề ước tính bản số đã được loại bỏ.

Dữ liệu ước tính bản số 1/31/2013 cho thấy:

Và dữ liệu ước tính bản số 2/28/2013 cho thấy:

Điều đó khiến bạn hài lòng trong giây lát, nhưng sau đó bạn nhận ra thời lượng thực thi truy vấn tổng thể có vẻ tương đối giống như trước đây. Bạn bắt đầu nghi ngờ rằng nhà phát triển sẽ hài lòng với kết quả của bạn. Bạn đã giải quyết được sai lệch ước tính bản số, nhưng không có hiệu suất tăng như mong đợi, bạn không chắc mình đã trợ giúp theo cách nào có ý nghĩa hay chưa.

Tại thời điểm này, bạn nhận ra rằng kế hoạch thực thi truy vấn chỉ là một tập hợp con của thông tin bạn có thể cần và vì vậy bạn mở rộng khả năng khám phá của mình hơn nữa bằng cách xem tab Bảng I / O. Bạn thấy kết quả sau cho quá trình thực thi 1/31/2013:

Và đối với lần thực thi 28/2/2013, bạn thấy dữ liệu tương tự:

Tại thời điểm đó, bạn tự hỏi liệu các hoạt động truy cập dữ liệu cho cả hai bảng là cần thiết trong mỗi kế hoạch. Nếu trình tối ưu hóa biết bạn chỉ cần các hàng tháng Giêng, tại sao lại truy cập vào tháng Hai và ngược lại? Bạn cũng nhớ rằng trình tối ưu hóa truy vấn không đảm bảo rằng không các hàng thực tế từ các tháng khác trong bảng "sai" trừ khi các đảm bảo đó được đưa ra một cách rõ ràng thông qua các ràng buộc trên chính bảng đó.

Bạn kiểm tra định nghĩa bảng qua sp_help cho từng bảng và bạn không thấy bất kỳ ràng buộc nào được xác định cho cả hai bảng.

Vì vậy, như một thử nghiệm, bạn thêm hai ràng buộc sau:

ALTER TABLE [dbo].[charge_jan]
  ADD CONSTRAINT charge_jan_chk CHECK
  (charge_dt >= '1/1/2013' AND charge_dt < '2/1/2013');
GO
 
ALTER TABLE [dbo].[charge_feb]
  ADD CONSTRAINT charge_feb_chk CHECK
  (charge_dt >= '2/1/2013' AND charge_dt < '3/1/2013');
GO

Bạn thực hiện lại các thủ tục đã lưu trữ và xem các hình dạng sơ đồ và ước tính bản số sau.

Ngày 31 tháng 1 năm 2013:

2/28/2013 thực hiện:

Nhìn lại Bảng I / O, bạn sẽ thấy kết quả sau cho quá trình thực thi 1/31/2013:

Và đối với lần thực thi 28/2/2013, bạn thấy dữ liệu tương tự, nhưng đối với bảng charge_feb:

Nhớ rằng bạn vẫn có RECOMPILE trong định nghĩa thủ tục được lưu trữ, bạn thử xóa nó đi và xem liệu bạn có thấy tác dụng tương tự không. Sau khi thực hiện việc này, bạn sẽ thấy trả về quyền truy cập hai bảng, nhưng không có lần đọc logic thực sự nào cho bảng không có hàng trong đó (so với kế hoạch ban đầu không có ràng buộc). Ví dụ:lần thực thi 1/31/2013 cho thấy đầu ra Bảng I / O sau:

Bạn quyết định tiếp tục với thử nghiệm tải các ràng buộc CHECK mới và giải pháp RECOMPILE, loại bỏ hoàn toàn quyền truy cập bảng khỏi kế hoạch (và các toán tử kế hoạch liên quan). Bạn cũng chuẩn bị cho mình cho cuộc tranh luận về khóa chỉ mục được phân nhóm và chỉ mục không được phân nhóm hỗ trợ phù hợp sẽ chứa một tập hợp khối lượng công việc rộng hơn hiện đang truy cập các bảng được liên kết.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách thêm ngày vào ngày trong T-SQL

  2. Toán tử SQL NOT cho người mới bắt đầu

  3. Mô hình Dịch vụ PAAS hoạt động như thế nào?

  4. Phân tích cú pháp các giá trị mặc định của tham số bằng PowerShell - Phần 1

  5. Tầm quan trọng của việc chọn kích thước máy ảo Azure thích hợp