Sau khi khôi phục Nhật ký vận chuyển đến máy chủ thứ cấp, việc thực thi thủ tục được lưu trữ đầu tiên bị chậm


7

Chúng tôi đã thiết lập vận chuyển nhật ký đến máy chủ SQL thứ cấp ở chế độ Chờ / Chỉ đọc để giảm tải tất cả việc tạo báo cáo SSRS.
Điều này hoạt động tốt trong các hạn chế áp đặt bởi:

  1. Giết người dùng trong quá trình khôi phục nhật ký giao dịch (chúng tôi đã khắc phục điều này bằng cách thiết lập nhiều phiên bản và khôi phục nhật ký giao dịch gần đây nhất bằng cách sử dụng lịch trình vòng tròn)
  2. Dữ liệu đã hết hạn, nhiều nhất là khung thời gian được chỉ định bởi công việc sao lưu / khôi phục nhật ký giao dịch theo lịch trình.

Thật không may, lần đầu tiên bất kỳ / tất cả các thủ tục được lưu trữ được chạy, sau khi nhật ký giao dịch được khôi phục, sẽ mất nhiều thời gian hơn để hoàn thành so với bình thường. Tất cả các lần thực hiện tiếp theo của cùng một thủ tục được lưu trữ hoàn thành trong thời gian dự kiến. Nếu sau đó chúng tôi thực hiện một thủ tục được lưu trữ khác, lần đầu tiên nó chậm và tất cả các lần thực hiện tiếp theo sẽ hoàn thành trong thời gian dự kiến.

Để tham khảo, sự khác biệt trong thực thi là ~ 00: 02 thông thường so với ~ 01: 00 trong lần chạy đầu tiên.

Tôi giả sử điều này có liên quan đến số liệu thống kê thực hiện của máy chủ hoặc tham số thủ tục được lưu trữ đánh hơi / kế hoạch thực hiện được lưu trữ.
Có cách nào để khắc phục vấn đề này không? Hoặc là điều này vốn có để khôi phục nhật ký giao dịch?

Nếu đó chỉ là lần thực hiện đầu tiên của bất kỳ thủ tục được lưu trữ nào, chúng ta có thể giải quyết vấn đề này một cách dễ dàng bằng cách thực hiện bất kỳ thủ tục được lưu trữ nào khi khôi phục, nhưng nó dường như ảnh hưởng đến lần đầu tiên tất cả các thủ tục được lưu trữ được thực thi.

Tôi đã thử chạy count( * )trên 11 bảng quy trình được lưu trữ mà tôi đang sử dụng để kiểm tra các lần chạm. Lần chạy đầu tiên mất 00:32 và lần đếm tiếp theo (*) mất 00:00. Thật không may, điều này không có bất kỳ tác động nào trong lần chạy đầu tiên của thủ tục được lưu trữ.

Tôi không thấy bất kỳ kết quả nào trên máy chủ chính hoặc máy chủ phụ của mình để biết is_temporarysố liệu thống kê, trước hoặc sau khi thực hiện quy trình được lưu trữ.

Tôi hiện đang


sử dụng Kế hoạch
thực hiện truy vấn SQL Server 2012 : Kế hoạch thực hiện truy vấn thoạt nhìn có vẻ khác biệt đáng kể, tuy nhiên, khi lưu kế hoạch thực hiện và mở tệp .sqlplan được tạo, chúng hoàn toàn giống nhau. Sự khác biệt dường như đến từ các phiên bản khác nhau của SSMS tôi đang sử dụng, 2014 trên máy chủ chính và 2018 trên phụ. Khi xem kế hoạch thực hiện trên phụ, nó hiển thị bên dưới% của mỗi nút và chi phí thời gian ### của ### (##%) - không phải là những con số đó, cũng không phải là kế hoạch thực hiện thực tế thay đổi khi thực hiện thêm.
Tôi cũng bao gồm số liệu thống kê của khách hàng và chúng hiển thị gần như giống hệt nhau, sự khác biệt duy nhất là máy chủ chính thực thi với 1,4 giây Thời gian chờ trả lời của máy chủ và thứ cấp mất 81,3 giây.

Tôi thấy một số lượng lớn các khóa PAGEIOLATCH_SH từ lần thực hiện đầu tiên, như bạn dự đoán:

diff after first exec vs diff after second exec
waiting_tasks_count    10903    918  
wait_time_ms          411129  12768  

Một trong những điều kỳ lạ về tình huống này là, ngoại trừ phần nhiều trường hợp của thiết lập, chúng tôi đã có máy chủ SSRS sản xuất của chúng tôi đọc từ cơ sở dữ liệu chỉ chờ / đọc được cung cấp bởi nhật ký giao dịch định kỳ và không có kinh nghiệm những sự chậm lại trong lần thực hiện đầu tiên của một thủ tục được lưu trữ. Người dùng của chúng tôi bị khởi động mỗi khi nhật ký giao dịch được khôi phục, tuy nhiên, đó là vấn đề thiết lập ở trên được cho là sẽ giải quyết.


Khi truy vấn từ sys.dm_exec_query_stats, bộ đệm cũ nhất của kế hoạch dường như không thay đổi, nhưng bộ đệm mới nhất (sau khi sắp xếp theo desc bởi Creation_time) được cập nhật và dường như được sao chép trong Log Shipping, vì chúng có cùng dấu thời gian sau khôi phục nhật ký giao dịch đã hoàn thành. Nó dường như không có bất kỳ ảnh hưởng nào đến việc thực hiện đầu tiên chậm.
RIanGillis

Câu trả lời:


8

Có một vài điều có thể xảy ra ở đây, đây là một danh sách không đầy đủ:

  • bộ đệm của kế hoạch thực hiện bị xóa bởi khôi phục nhật ký, vì vậy các kế hoạch sẽ cần được biên dịch lại lần đầu tiên. Nếu kế hoạch của bạn có thời gian biên dịch dài, điều này có thể giải thích sự khác biệt. Bạn đã không đề cập chính xác thời gian trì hoãn trong lần chạy đầu tiên là bao lâu so với lần chạy tiếp theo
    • cái này có vẻ như ít có khả năng nhất - bạn có thể thấy thời gian biên dịch kế hoạch của mình trong XML kế hoạch thực hiện thực tế
  • vùng đệm cũng bị xóa trong quá trình khôi phục, vì vậy tất cả dữ liệu phải được đọc từ đĩa trong lần thực hiện đầu tiên
    • nếu đây là trường hợp, bạn có thể sẽ thấy sự PAGEIOLATCH*chờ đợi cao trong lần chạy đầu tiên nếu bạn kiểm tra số liệu thống kê chờ

Một số điều bạn có thể làm để giảm thiểu điều này là

  • "làm nóng" bộ đệm bộ đệm (bằng cách đọc tất cả dữ liệu từ các bảng quan trọng vào bộ nhớ bằng cách sử dụng SELECT COUNT(*) FROM dbo.YourTable),
  • "làm nóng" bộ đệm cache bằng cách chạy tất cả các quy trình được lưu trữ quan trọng dưới dạng bước hậu khôi phục

Cung cấp cho chúng tôi một ví dụ "nhanh" và "chậm" về kế hoạch thực hiện có thể giúp chúng tôi theo dõi chính xác điều gì đang xảy ra.


Nếu bạn đang sử dụng SQL Server 2012 hoặc mới hơn, thì có thể các cập nhật thống kê đồng bộ hóa đang gây ra sự chậm trễ. Các "số liệu thống kê thứ cấp có thể đọc" này được tạo trong TempDB, vì thứ cấp vận chuyển nhật ký là chỉ đọc. Bạn có thể đọc thêm về điều đó ở đây (bài viết về AGs, nhưng điều tương tự áp dụng trong kịch bản này):

Luôn luôn: Cung cấp số liệu thống kê mới nhất trên cơ sở dữ liệu thứ cấp, chỉ đọc và cơ sở dữ liệu có thể đọc

Nếu đây là vấn đề gây ra sự chậm chạp của bạn, thì một giải pháp sẽ là tìm các số liệu thống kê đó, sau đó tạo chúng trong cơ sở dữ liệu sản xuất để chúng được cập nhật và có sẵn sau khi khôi phục. Bạn có thể tìm số liệu thống kê tạm thời với truy vấn này:

SELECT * FROM sys.stats WHERE is_temporary = 1;

Dựa trên các số liệu thống kê chờ đợi mà bạn cung cấp và thực tế là các kế hoạch là như nhau, điều này khá thuyết phục do nhóm bộ đệm bị xóa bởi khôi phục nhật ký.

Khi chạy bình thường, bạn nhận được 12.768 ms (gần 13 giây) IO chờ.
Trong lần chạy đầu tiên, bạn nhận được 411.129 ms (gần 7 phút ) IO chờ đợi.

Cách SELECT COUNT(*)tiếp cận bạn đã thử có thể không có ích do các chỉ mục khác nhau được sử dụng bởi quy trình thực tế so với COUNT(*)truy vấn. Bạn có một vài lựa chọn ở đây:

  1. Đi qua từng kế hoạch thực hiện và ghi chú các chỉ mục đang được sử dụng, sau đó kéo các chỉ mục đó vào bộ nhớ như một bước hậu khôi phục - sử dụng gợi ý chỉ mục lần này ( SELECT COUNT(*) FROM dbo.YourTable WITH (INDEX (IX_Index_Being_Used_By_Proc)))
  2. Trải qua quá trình kịch bản ra một quy trình để chạy từng thủ tục như một bước hậu khôi phục (điều này có vẻ dễ hơn một chút so với tùy chọn 1)
  3. Điều chỉnh các truy vấn sao cho chúng không cần thực hiện nhiều lần đọc (không chắc mức độ khả thi này)
  4. Tăng tốc hệ thống con I / O - nhận đĩa nhanh hơn, SSD cục bộ, nhiều kênh hơn đến SAN, v.v. (đây có lẽ là tùy chọn khó nhất và đắt nhất
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.