Chỉ số không liên tục RESOURCE_SEMAPHORE_QUERY_COMPILE


8

Tôi đang cố gắng khắc phục một số đột biến CPU không liên tục mà chúng tôi đang chứng kiến ​​trên một trong các Máy chủ SQL sản xuất của chúng tôi. Chúng tôi đang chạy SQL Server 2008 R2 Standard Edition với RAM 28 GB và 4 lõi CPU. Khi điều này xảy ra, chúng tôi nhận thấy một số lượng lớn RESOURCE_SEMAPHORE_QUERY_COMPILER chờ đợi, kéo dài trong khoảng một hoặc hai phút và sau đó dừng lại, sau đó việc sử dụng CPU trở lại bình thường.

Sau khi nghiên cứu điều này, tôi hiểu rằng điều này thường xảy ra do biên dịch nhiều kế hoạch thực hiện không thể sử dụng lại, hiện chúng tôi đang nghiên cứu các thay đổi cho ứng dụng của chúng tôi để giải quyết.

Hành vi này cũng có thể được kích hoạt bởi kế hoạch trục xuất bộ nhớ cache do áp lực bộ nhớ? Nếu vậy, làm thế nào tôi sẽ kiểm tra này? Tôi đang cố gắng xem liệu có biện pháp khắc phục ngắn hạn nào chúng tôi có thể làm hay không, như nâng cấp RAM máy chủ, cho đến khi chúng tôi triển khai sửa lỗi ứng dụng của mình. Tùy chọn ngắn hạn duy nhất khác mà tôi có thể nghĩ đến là chuyển một số cơ sở dữ liệu bận rộn nhất của chúng tôi sang máy chủ khác.

Câu trả lời:


6

Tôi tin rằng bạn sẽ thấy triệu chứng này nếu bạn có RẤT NHIỀU kế hoạch truy vấn lớn đang đấu tranh cho bộ nhớ để biên dịch (điều này rất ít liên quan đến việc chạy chính truy vấn). Để đạt được điều này, tôi nghi ngờ bạn đang sử dụng ORM hoặc một loại ứng dụng nào đó tạo ra nhiều truy vấn độc đáo nhưng tương đối phức tạp. SQL Server có thể chịu áp lực bộ nhớ vì những thứ như hoạt động truy vấn lớn, nhưng nghĩ thêm có khả năng là hệ thống của bạn được cấu hình với bộ nhớ ít hơn nhiều so với nhu cầu (hoặc không bao giờ có đủ bộ nhớ để đáp ứng tất cả các truy vấn bạn Đang cố gắng biên dịch hoặc có các quy trình khác trên hộp đang đánh cắp bộ nhớ từ SQL Server).

Bạn có thể xem SQL Server được cấu hình bằng cách sử dụng:

EXEC sp_configure 'max server memory';    -- max configured in MB

SELECT counter_name, cntr_value
  FROM sys.dm_os_performance_counters
  WHERE counter_name IN
  (
    'Total Server Memory (KB)',    -- max currently granted
    'Target Server Memory (KB)'    -- how much SQL Server wished it had
  );

Bạn có thể xác định các gói được lưu trong bộ nhớ cache yêu cầu bộ nhớ biên dịch nhiều nhất với truy vấn Jonathan Kehayias sau đây , được điều chỉnh một chút:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT TOP (10) CompileTime_ms, CompileCPU_ms, CompileMemory_KB,
  qs.execution_count,
  qs.total_elapsed_time/1000.0 AS duration_ms,
  qs.total_worker_time/1000.0 as cputime_ms,
  (qs.total_elapsed_time/qs.execution_count)/1000.0 AS avg_duration_ms,
  (qs.total_worker_time/qs.execution_count)/1000.0 AS avg_cputime_ms,
  qs.max_elapsed_time/1000.0 AS max_duration_ms,
  qs.max_worker_time/1000.0 AS max_cputime_ms,
  SUBSTRING(st.text, (qs.statement_start_offset / 2) + 1,
    (CASE qs.statement_end_offset
      WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset
     END - qs.statement_start_offset) / 2 + 1) AS StmtText,
  query_hash, query_plan_hash
FROM
(
  SELECT 
    c.value('xs:hexBinary(substring((@QueryHash)[1],3))', 'varbinary(max)') AS QueryHash,
    c.value('xs:hexBinary(substring((@QueryPlanHash)[1],3))', 'varbinary(max)') AS QueryPlanHash,
    c.value('(QueryPlan/@CompileTime)[1]', 'int') AS CompileTime_ms,
    c.value('(QueryPlan/@CompileCPU)[1]', 'int') AS CompileCPU_ms,
    c.value('(QueryPlan/@CompileMemory)[1]', 'int') AS CompileMemory_KB,
    qp.query_plan
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY qp.query_plan.nodes('ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') AS n(c)
) AS tab
JOIN sys.dm_exec_query_stats AS qs ON tab.QueryHash = qs.query_hash
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
ORDER BY CompileMemory_KB DESC
OPTION (RECOMPILE, MAXDOP 1);

Bạn có thể thấy cách bộ đệm kế hoạch đang được sử dụng với những điều sau đây:

SELECT objtype, cacheobjtype,
    AVG(size_in_bytes*1.0)/1024.0/1024.0,
    MAX(size_in_bytes)/1024.0/1024.0,
    SUM(size_in_bytes)/1024.0/1024.0,
    COUNT(*)
FROM sys.dm_exec_cached_plans
GROUP BY GROUPING SETS ((),(objtype, cacheobjtype))
ORDER BY objtype, cacheobjtype;

Khi bạn gặp phải tình trạng chờ đợi semaphore cao, hãy kiểm tra xem liệu các kết quả truy vấn này có thay đổi đáng kể so với trong hoạt động "bình thường" không:

SELECT resource_semaphore_id, -- 0 = regular, 1 = "small query"
  pool_id,
  available_memory_kb,
  total_memory_kb,
  target_memory_kb
FROM sys.dm_exec_query_resource_semaphores;

SELECT StmtText = SUBSTRING(st.[text], (qs.statement_start_offset / 2) + 1,
        (CASE qs.statement_end_offset
          WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset
         END - qs.statement_start_offset) / 2 + 1),
  r.start_time, r.[status], DB_NAME(r.database_id), r.wait_type, 
  r.last_wait_type, r.total_elapsed_time, r.granted_query_memory,
  m.requested_memory_kb, m.granted_memory_kb, m.required_memory_kb,
  m.used_memory_kb
FROM sys.dm_exec_requests AS r
INNER JOIN sys.dm_exec_query_stats AS qs
ON r.plan_handle = qs.plan_handle
INNER JOIN sys.dm_exec_query_memory_grants AS m
ON r.request_id = m.request_id
AND r.plan_handle = m.plan_handle
CROSS APPLY sys.dm_exec_sql_text(r.plan_handle) AS st;

Và bạn cũng có thể muốn xem và xem cách phân phối bộ nhớ:

DBCC MEMORYSTATUS;

Và có một số thông tin tốt ở đây về lý do tại sao bạn có thể thấy số lượng biên dịch / biên dịch lại cao (sẽ đóng góp cho sự chờ đợi đó):

http://technet.microsoft.com/en-us/library/ee343986(v=sql.100).aspx

http://technet.microsoft.com/en-us/library/cc293620.aspx

Bạn có thể kiểm tra số lượng biên dịch / biên dịch lại cao bằng các bộ đếm sau:

SELECT counter_name, cntr_value
  FROM sys.dm_os_performance_counters
  WHERE counter_name IN 
  (
    'SQL Compilations/sec',
    'SQL Re-Compilations/sec'
  );

Và bạn có thể kiểm tra áp suất bộ nhớ trong dẫn đến việc trục xuất - các bộ đếm khác không ở đây sẽ chỉ ra rằng điều gì đó không tốt đang xảy ra với bộ đệm của kế hoạch:

SELECT * FROM sys.dm_os_memory_cache_clock_hands 
  WHERE [type] IN (N'CACHESTORE_SQLCP', N'CACHESTORE_OBJCP');

LƯU Ý Hầu hết các số liệu này không có phép thuật "trời ơi tôi cần phải hoảng sợ hoặc làm gì đó!" ngưỡng. Những gì bạn cần làm là thực hiện các phép đo trong quá trình hoạt động bình thường của hệ thống và xác định các ngưỡng này dành cho phần cứng, cấu hình và khối lượng công việc của bạn. Khi bạn hoảng loạn làm điều gì đó là khi hai điều kiện là đúng:

  1. các số liệu khác nhau đáng kể từ các giá trị bình thường; và,
  2. thực sự có một vấn đề về hiệu năng xảy ra (như CPU ​​của bạn tăng đột biến) - nhưng chỉ khi chúng thực sự can thiệp vào bất cứ điều gì. Ngoài việc thấy CPU tăng đột biến, bạn có thấy bất kỳ triệu chứng nào khác không? Nói cách khác, sự tăng đột biến là triệu chứng, hay là sự tăng đột biến gây ra các triệu chứng khác? Người dùng của hệ thống có bao giờ nhận thấy? Rất nhiều người luôn theo đuổi người tiêu dùng chờ đợi cao nhất của họ, đơn giản vì đó là mức cao nhất. Một cái gì đó luôn luôn là người tiêu dùng chờ đợi cao nhất - bạn phải biết rằng nó thay đổi đủ so với hoạt động bình thường mà nó chỉ ra một vấn đề hoặc một số thay đổi đáng kể.

Optimize for ad hoc workloadslà một thiết lập tuyệt vời cho 99% khối lượng công việc ngoài kia, nhưng sẽ không hữu ích lắm trong việc giảm chi phí biên dịch - nó nhằm mục đích giảm sự phình to bộ nhớ cache của kế hoạch bằng cách ngăn kế hoạch sử dụng một lần lưu trữ toàn bộ kế hoạch cho đến khi nó được thực hiện hai lần . Ngay cả khi bạn chỉ lưu trữ sơ khai trong bộ đệm của kế hoạch, bạn vẫn phải biên dịch toàn bộ kế hoạch để thực hiện truy vấn. Có lẽ điều mà @Kahn muốn đề xuất là đặt tham số hóa mức cơ sở dữ liệu thành bắt buộc , điều này sẽ có khả năng cung cấp việc sử dụng lại kế hoạch tốt hơn (nhưng nó thực sự phụ thuộc vào mức độ duy nhất của tất cả các truy vấn chi phí cao này).

Ngoài ra một số thông tin tốt trong bài báo trắng này về kế hoạch lưu trữ và bộ nhớ đệm.


Optimize for ad hoc workloadsTuy nhiên, hiện tại chúng tôi có bộ, như bạn đã đề cập, nó không thực sự liên quan đến vấn đề cụ thể này. Chúng tôi có mã tạo ra rất nhiều truy vấn duy nhất, một số từ một công cụ ORM, một số được mã hóa bằng tay. Theo tôi biết, các đột biến CPU không xảy ra đủ lâu để người dùng của chúng tôi chú ý. Đặt cơ sở dữ liệu thành tham số bắt buộc nghe có vẻ nguy hiểm đối với tôi.
DanM

Một câu hỏi - khi bạn kiểm tra các phần tổng hợp cao, cái gì thực sự cấu thành một số cao? Tôi nghĩ rằng các phần tổng hợp / giây chỉ có ý nghĩa khi so sánh với số lượng yêu cầu lô / giây.
DanM

@DanM như tôi đã nói ở trên, không có cách nào để tôi biết những gì có thể cao cho môi trường của bạn, bởi vì tôi không biết điều gì là bình thường cho môi trường của bạn. Nếu số lượng gần hoặc cao hơn số lượng yêu cầu lô / giây, đó có thể là một chỉ báo, nhưng một lần nữa, nó phụ thuộc. Ví dụ: nếu các lô của bạn bao gồm 5000 câu lệnh và 10 trong số chúng yêu cầu biên dịch lại (vì điều này có thể xảy ra ở mức câu lệnh), comp / sec sẽ là 10 lần so với lô / giây. Đó có phải là vấn đề không?
Aaron Bertrand

@DanM Ngoài ra, bạn nên thực hiện bất kỳ đề xuất nào để thay đổi cơ sở dữ liệu hoặc cài đặt toàn cầu với tuyên bố từ chối ngụ ý rằng đó là điều bạn nên kiểm tra và không chỉ kích hoạt vì ai đó trên Internet đã nói như vậy. :-) Tôi cố gắng giải thích làm thế nào và tại sao một sự thay đổi có thể giúp ích, nhưng tôi không luôn nhớ nói rõ: kiểm tra nó trước .
Aaron Bertrand

Tôi thấy quan điểm của bạn - những gì cấu thành nên các phần tổng hợp "cao" hoàn toàn phụ thuộc vào môi trường.
DanM

-1

Lý do điển hình nhất cho đến nay tôi đã thấy những chờ đợi đó xuất hiện, là kết quả của các chỉ mục bị phân mảnh hoặc không đủ và số liệu thống kê có kích thước mẫu không đủ hoặc đã lỗi thời. Điều này dẫn đến việc quét toàn bộ bảng lớn sẽ chiếm hết bộ nhớ, từ đó tạo ra một triệu chứng mà chúng ta thường thấy là RESOURCE_SEMAPHORE_QUERY_COMPILE.

Cách dễ nhất để xác minh điều này là kiểm tra xem các truy vấn có chạy quét toàn bộ bảng / quét chỉ mục hay không, khi nào chúng nên thực hiện tìm kiếm chỉ mục. Nếu bạn có một truy vấn vấn đề mà bạn có thể tái tạo vấn đề - việc chẩn đoán và khắc phục vấn đề này trở nên rất dễ dàng.

Tôi sẽ kiểm tra các chỉ mục trên các bảng bị ảnh hưởng bởi các truy vấn vấn đề đó - tức là. kiểm tra phân mảnh chỉ mục, các chỉ mục được lọc tiềm năng không được sử dụng, các chỉ mục bị thiếu mà bạn có thể muốn tạo, v.v. Ngoài ra, hãy cập nhật số liệu thống kê của họ với FULLSCAN càng sớm càng tốt.

Một điểm tốt cần nhớ là bảng vấn đề của bạn có thể không phải là người duy nhất cần điều này. Ví dụ: nếu bạn có một truy vấn tìm nạp dữ liệu từ 10 bảng, trình lập kế hoạch thực thi đôi khi có thể cho thấy rằng nó không sử dụng chỉ mục trên bảng 1, nhưng khi bạn kiểm tra chỉ mục trên bảng 1 thì thực sự ổn. Trình lập kế hoạch truy vấn có thể giải quyết để tìm nạp dữ liệu trên bảng 1 với quét toàn bộ bảng một cách chính xác, vì chẳng hạn chỉ mục bị lỗi / không đủ trên bảng 7, đã trả về rất nhiều dữ liệu nên đây sẽ là tùy chọn nhanh hơn. Vì vậy, chẩn đoán những điều này đôi khi có thể khó khăn.

Ngoài ra, nếu bạn có nhiều truy vấn cơ sở mã chỉ với một vài thay đổi trong các giá trị biến, bạn có thể muốn xem xét kích hoạt tối ưu hóa cho khối lượng công việc ad hoc . Về cơ bản những gì nó làm là lưu trữ một sơ đồ của kế hoạch được biên dịch thay vì toàn bộ kế hoạch, tiết kiệm tài nguyên khi bạn không bao giờ hoàn toàn có được các kế hoạch chính xác giống nhau mỗi lần.


Hầu hết những điều bạn nêu bật sẽ gây ra các kế hoạch truy vấn không hiệu quả, không phải thời gian biên dịch cao. IMHO.
Aaron Bertrand

Tuy nhiên, tôi đã thấy điều này xảy ra nhiều lần và sự chờ đợi đó thường chính xác là những gì diễn ra sau đó. Rõ ràng là tôi không biết mức độ phổ biến của nó hoặc nếu nó được áp dụng ở đây, nhưng các phương pháp được đề cập ở trên đã sửa nó.
Kahn

Là một chỉnh sửa sau, trong trường hợp của chúng tôi, nó xuất hiện trong một DB khá lớn sau khi các chỉ số / thống kê quan trọng bị ảnh hưởng được sử dụng bởi một số lượng lớn các truy vấn được chạy mọi lúc.
Kahn

1
Phải, và sự chờ đợi biên dịch xuất hiện do chỉ số / số liệu thống kê đã bị thay đổi, điều này khiến tất cả các kế hoạch có liên quan được biên dịch lại, không phải vì chúng bị phân mảnh hoặc lỗi thời (như trạng thái câu trả lời của bạn).
Aaron Bertrand
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.