Không bao giờ kết thúc tìm kiếm Store Store


10

Tôi sẽ nói ngay từ đầu rằng câu hỏi của tôi / vấn đề trông giống như này trước đó, nhưng vì tôi không chắc chắn nếu nguyên nhân hoặc các thông tin bắt đầu là như nhau, tôi quyết định gửi câu hỏi của tôi với một số chi tiết.

Vấn đề trong tầm tay:

  • vào một giờ lạ (gần cuối ngày làm việc), một cá thể sản xuất bắt đầu hành xử thất thường:
    • CPU cao chẳng hạn (từ mức cơ bản ~ 30%, nó tăng lên gấp đôi và vẫn đang tăng lên)
    • số lượng giao dịch / giây tăng lên (mặc dù tải ứng dụng không thấy bất kỳ thay đổi nào)
    • tăng số phiên nhàn rỗi
    • các sự kiện chặn lạ giữa các phiên không bao giờ hiển thị hành vi này (thậm chí đọc các phiên không được cam kết đã gây ra chặn)
    • chờ đợi hàng đầu cho khoảng thời gian là chốt trang không ở vị trí số 1, với khóa chiếm vị trí thứ 2

Sự khảo sát ban đầu:

  • sử dụng sp_whoIsActive, chúng tôi thấy rằng một truy vấn được thực thi bởi công cụ giám sát của chúng tôi quyết định chạy cực kỳ chậm và lấy rất nhiều CPU, điều mà trước đây không xảy ra;
  • mức độ cô lập của nó đã được đọc không cam kết;
  • chúng tôi đã xem xét kế hoạch mà chúng tôi thấy các con số lập dị: StatementEstRows = "3.86846e + 010" với khoảng 150 TB dữ liệu ước tính sẽ được trả về
  • chúng tôi nghi ngờ tính năng giám sát truy vấn của công cụ giám sát là nguyên nhân, vì vậy chúng tôi đã vô hiệu hóa tính năng này (chúng tôi cũng đã mở một vé với nhà cung cấp của chúng tôi để kiểm tra xem họ có biết về bất kỳ vấn đề nào không)
  • từ sự kiện đầu tiên đó, nó đã xảy ra thêm một vài lần nữa, với mỗi lần chúng ta giết phiên, mọi thứ trở lại bình thường;
  • chúng tôi nhận thấy truy vấn cực kỳ giống với một trong những truy vấn được MS sử dụng trong giám sát BOL cho Truy vấn cửa hàng truy vấn - Các truy vấn gần đây đã hồi quy về hiệu suất (so sánh các thời điểm khác nhau)
  • chúng tôi chạy cùng một truy vấn theo cách thủ công và thấy hành vi tương tự (CPU được sử dụng ngày càng tăng, chờ đợi chốt, khóa bất ngờ .. vv)

Truy vấn có tội:

Select qt.query_sql_text, 
    q.query_id, 
    qt.query_text_id, 
    rs1.runtime_stats_id AS runtime_stats_id_1,
    interval_1 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi1.start_time), 
    p1.plan_id AS plan_1, 
    rs1.avg_duration AS avg_duration_1, 
    rs2.avg_duration AS avg_duration_2,
    p2.plan_id AS plan_2, 
    interval_2 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi2.start_time), 
    rs2.runtime_stats_id AS runtime_stats_id_2
From sys.query_store_query_text AS qt 
Inner Join sys.query_store_query AS q 
    ON qt.query_text_id = q.query_text_id 
Inner Join sys.query_store_plan AS p1 
    ON q.query_id = p1.query_id 
Inner Join sys.query_store_runtime_stats AS rs1 
    ON p1.plan_id = rs1.plan_id 
Inner Join sys.query_store_runtime_stats_interval AS rsi1 
    ON rsi1.runtime_stats_interval_id = rs1.runtime_stats_interval_id 
 Inner Join sys.query_store_plan AS p2 
    ON q.query_id = p2.query_id 
Inner Join sys.query_store_runtime_stats AS rs2 
    ON p2.plan_id = rs2.plan_id 
Inner Join sys.query_store_runtime_stats_interval AS rsi2 
    ON rsi2.runtime_stats_interval_id = rs2.runtime_stats_interval_id
Where rsi1.start_time > DATEADD(hour, -48, GETUTCDATE()) 
    AND rsi2.start_time > rsi1.start_time 
    AND p1.plan_id <> p2.plan_id
    AND rs2.avg_duration > rs1.avg_duration * 2
Order By q.query_id, rsi1.start_time, rsi2.start_time

Cài đặt và thông tin:

  • SQL Server 2016 SP1 CU4 Enterprise trên cụm Windows Server 2012R2
  • Cửa hàng truy vấn được bật và định cấu hình như mặc định (không thay đổi cài đặt)
  • cơ sở dữ liệu được nhập từ phiên bản SQL 2005 (và vẫn ở mức tương thích 100)

Quan sát thực nghiệm:

  • do số liệu thống kê cực kỳ kỳ quặc, chúng tôi đã lấy tất cả các đối tượng * plan_persist ** được sử dụng trong kế hoạch ước tính xấu (chưa có kế hoạch thực tế, vì truy vấn không bao giờ kết thúc) và kiểm tra thống kê, một số chỉ mục được sử dụng trong kế hoạch không có bất kỳ thống kê nào (DBCC SHOWSTATISTICS không trả lại bất cứ điều gì, chọn từ sys.stats hiển thị hàm NULL stats_date () cho một số chỉ mục

Giải pháp nhanh và bẩn:

  • tự tạo các thống kê bị thiếu trên các đối tượng hệ thống liên quan đến Kho lưu trữ truy vấn hoặc
  • buộc truy vấn chạy bằng CE mới (trackflag) - cũng sẽ tạo / cập nhật các số liệu thống kê cần thiết hoặc
  • thay đổi mức độ tương thích của cơ sở dữ liệu thành 130 (do đó, theo mặc định, nó sẽ sử dụng CE mới)

Vì vậy, câu hỏi thực sự của tôi sẽ là:

Tại sao một truy vấn trên Cửa hàng truy vấn sẽ gây ra vấn đề về hiệu suất trên toàn bộ phiên bản? Có phải chúng ta đang ở trong một lãnh thổ lỗi với Truy vấn Cửa hàng?

PS: Tôi sẽ tải lên một số tệp (màn hình in, số liệu thống kê và kế hoạch IO) trong một thời gian ngắn.

Các tập tin được thêm vào Dropbox .

Kế hoạch 1 - kế hoạch dự tính lập dị ban đầu trong sản xuất

Kế hoạch 2 - kế hoạch thực tế, CE cũ, trong một env thử nghiệm (cùng hành vi, cùng chỉ số lập dị)

Kế hoạch 3 - kế hoạch thực tế, CE mới, trong một thử nghiệm env


1
Cuối cùng chúng tôi đã vô hiệu hóa cửa hàng truy vấn, chúng tôi chắc chắn nguyên nhân gốc là gì (chắc chắn chúng tôi có nhiều hơn 1 vấn đề). Cuối cùng, CPU sẽ tăng tốc mọi thứ chúng tôi đã nhấp để hiển thị số liệu thống kê từ cửa hàng truy vấn.
A_V

Câu trả lời:


6

Như tôi đã nói trong câu trả lời, thử nghiệm thực nghiệm cho thấy rằng có các chỉ mục trên các đối tượng hệ thống sys.plan_persisted * mà không có bất kỳ thống kê (không có) nào được tạo ra trên chúng. Tôi nghi ngờ rằng đó là do cơ sở dữ liệu được di chuyển từ phiên bản SQL 2005 và được giữ trong một thời gian ở mức tương thích 100, do đó CE mới không được sử dụng.

Kiểm tra số hàng:

Select count(1) from NoNameDB.sys.plan_persist_runtime_stats with (nolock) --60362   
Select count(1) from NoNameDB.sys.plan_persist_plan with (nolock) --1853    
Select count(1) from NoNameDB.sys.plan_persist_runtime_stats_interval with (nolock) --671    
Select count(1) from NoNameDB.sys.plan_persist_query with (nolock) --1091    
Select count(1) from NoNameDB.sys.plan_persist_query_text with (nolock) --911

Điều này cho thấy các ước tính ban đầu là sai. Thực hiện với kết nối DAC, nếu không các bảng không có sẵn để truy vấn.

Kiểm tra số liệu thống kê:

DBCC SHOW_STATISTICS ('sys.plan_persist_runtime_stats_interval', plan_persist_runtime_stats_interval_cidx);    
DBCC SHOW_STATISTICS ('sys.plan_persist_runtime_stats', plan_persist_runtime_stats_idx1);    
DBCC SHOW_STATISTICS ('sys.plan_persist_runtime_stats', plan_persist_runtime_stats_cidx);    
DBCC SHOW_STATISTICS ('sys.plan_persist_plan', plan_persist_plan_cidx);    
DBCC SHOW_STATISTICS ('sys.plan_persist_plan', plan_persist_plan_idx1);    
DBCC SHOW_STATISTICS ('sys.plan_persist_query', plan_persist_query_cidx)    
DBCC SHOW_STATISTICS ('sys.plan_persist_query_text', plan_persist_query_text_cidx);

Điều này cho thấy một số chỉ mục có số liệu thống kê trống (thiếu, không có, không).

Sửa lỗi ban đầu:

UPDATE STATISTICS sys.plan_persist_runtime_stats WITH fullscan;
UPDATE STATISTICS sys.plan_persist_plan WITH fullscan;
UPDATE STATISTICS sys.plan_persist_runtime_stats_interval WITH fullscan;
UPDATE STATISTICS sys.plan_persist_query WITH fullscan;
UPDATE STATISTICS sys.plan_persist_query_text WITH fullscan;

Loại này đã cố định các số liệu thống kê và thực hiện truy vấn kết thúc sau 10-12 giây.

Sửa lỗi thứ hai :

(chỉ được xác minh trên môi trường thử nghiệm) và rất có thể là đúng, vì nó cho thấy số liệu thống kê tốt nhất cho truy vấn, là thay đổi mức độ tương thích của cơ sở dữ liệu thành 130. Kết quả cuối cùng là truy vấn kết thúc sau khoảng 10-12 giây với thống kê số bình thường (10k hàng).

Sửa chữa trung gian :

DBCC TRACEON (2312) -- new CE

Một số trợ giúp liên quan về số liệu thống kê trên các bảng ẩn hệ thống.


3

Vấn đề cơ bản, có thể nhìn thấy nếu bạn mở kế hoạch thực tế trong SSMS và xem xét việc sử dụng CPU (hoặc kiểm tra XML), là nút 32, TVF. Thủ phạm trong các truy vấn Store Store chậm là truy cập lặp lại của các TVF trong bộ nhớ .

Chi phí TVF

Không quan trọng có bao nhiêu hàng được trả về từ các TVF này, chỉ có số lần chúng được truy cập. Việc khắc phục sẽ là bất cứ điều gì bạn có thể làm để đẩy lùi kế hoạch của bạn khỏi việc đọc chúng nhiều lần.

Dựa trên việc gỡ lỗi giới hạn của tôi (cả về kỹ năng và thời gian sử dụng), giả thuyết của tôi là toàn bộ bộ nhớ được gán cho thành phần trong bộ nhớ cụ thể của dữ liệu Kho lưu trữ truy vấn được quét với mỗi lần thực hiện TVF. Tôi đã không thể ảnh hưởng đến việc phân bổ bộ nhớ này với một trong hai sp_query_store_flush_dbhoặc DBCC FREESYSTEMCACHE.

Các giải pháp thành công cho đến nay bao gồm các hướng dẫn kế hoạch, gợi ý ( OPTION(HASH JOIN, LOOP JOIN)đã hoạt động đủ tốt cho tôi cho đến nay) và chạy các truy vấn Cửa hàng Truy vấn trên nút chỉ đọc của AG.

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.