2008-08-26 12 views
29

Có thể phân tích mức sử dụng CPU theo cơ sở dữ liệu không? Tôi rất lý tưởng khi tìm kiếm một giao diện kiểu Task Manager cho máy chủ SQL, nhưng thay vì xem xét việc sử dụng CPU của mỗi PID (như taskmgr) hoặc mỗi SPID (như spwho2k5), tôi muốn xem tổng mức sử dụng CPU của mỗi cơ sở dữ liệu. Giả sử một cá thể SQL đơn.Sử dụng CPU theo cơ sở dữ liệu?

Tôi nhận ra rằng các công cụ có thể được ghi để thu thập dữ liệu này và báo cáo, nhưng tôi tự hỏi liệu có công cụ nào cho phép tôi xem trực tiếp cơ sở dữ liệu nào đang đóng góp nhiều nhất vào tải CPU sqlservr.exe hay không.

Trả lời

81

Sắp xếp. Kiểm tra truy vấn này:

SELECT total_worker_time/execution_count AS AvgCPU 
, total_worker_time AS TotalCPU 
, total_elapsed_time/execution_count AS AvgDuration 
, total_elapsed_time AS TotalDuration 
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads 
, (total_logical_reads+total_physical_reads) AS TotalReads 
, execution_count 
, 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 txt 
, query_plan 
FROM sys.dm_exec_query_stats AS qs 
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st 
cross apply sys.dm_exec_query_plan (qs.plan_handle) AS qp 
ORDER BY 1 DESC 

Điều này sẽ giúp bạn có được các truy vấn trong bộ đệm kế hoạch để biết số lượng CPU mà chúng đã sử dụng hết. Bạn có thể chạy định kỳ này, như trong một tác vụ SQL Agent, và chèn các kết quả vào một bảng để đảm bảo dữ liệu vẫn còn tồn tại sau khi khởi động lại.

Khi bạn đọc kết quả, có thể bạn sẽ nhận ra lý do tại sao chúng tôi không thể tương quan dữ liệu đó trực tiếp trở lại cơ sở dữ liệu riêng lẻ. Đầu tiên, một truy vấn đơn lẻ cũng có thể ẩn cha mẹ cơ sở dữ liệu thực sự của nó bằng cách thực hiện các thủ thuật như sau:

USE msdb 
DECLARE @StringToExecute VARCHAR(1000) 
SET @StringToExecute = 'SELECT * FROM AdventureWorks.dbo.ErrorLog' 
EXEC @StringToExecute 

Truy vấn sẽ được thực hiện trong MSDB, nhưng sẽ thăm dò ý kiến ​​từ AdventureWorks. Chúng ta nên chỉ định mức tiêu thụ CPU ở đâu?

Nó trở nên tệ hơn khi bạn:

  • Tham giữa nhiều cơ sở dữ liệu
  • Chạy một giao dịch trong nhiều cơ sở dữ liệu, và nỗ lực khóa kéo dài nhiều cơ sở dữ liệu
  • việc Run SQL Agent trong MSDB rằng "làm việc" trong MSDB, nhưng sao lưu cơ sở dữ liệu riêng lẻ

Nó cứ tiếp tục và bật. Đó là lý do tại sao nó làm cho tinh thần để điều chỉnh hiệu suất ở cấp truy vấn thay vì mức cơ sở dữ liệu.

Trong SQL Server 2008R2, Microsoft đã giới thiệu các tính năng quản lý ứng dụng và quản lý ứng dụng, cho phép chúng tôi đóng gói một cơ sở dữ liệu trong gói DAC có thể phân phối và triển khai. ứng dụng của họ. Nó vẫn không làm những gì bạn đang tìm kiếm, mặc dù.

Để biết thêm, hãy xem T-SQL repository at Toad World's SQL Server wiki (formerly at SQLServerPedia).

Cập nhật ngày 1/29 để bao gồm tổng số thay vì chỉ số trung bình.

+1

Hãy tha thứ cho sự thiếu hiểu biết của tôi, nhưng các đơn vị của CPC trung bình và CPC trung bình là gì? – Portman

+1

Mili giây cho cả hai - mili giây của thời gian CPU và mili giây của thời lượng. Chúng có thể khác nhau bởi vì các truy vấn có thể chờ trên IO, khóa, máy khách, v.v. Tôi sẽ sửa đổi truy vấn để lấy tổng số quá. (Tôi định nói chân-pound nhưng tôi không thể giữ một khuôn mặt thẳng ảo.) –

15

Máy chủ SQL (bắt đầu với 2000) sẽ cài đặt bộ đếm hiệu suất (có thể xem từ Trình theo dõi hiệu suất hoặc Perfmon).

Một trong những loại truy cập (từ một SQL Server 2005 cài đặt là :) - SQLServer: Cơ sở dữ liệu

Với một ví dụ cho mỗi cơ sở dữ liệu. Các quầy có sẵn tuy nhiên không cung cấp một CPU% Utilization truy cập hoặc một cái gì đó tương tự, mặc dù có một số tỷ lệ quầy, mà bạn có thể sử dụng để có được một ước tính tốt của CPU. Ví dụ, nếu bạn có 2 cơ sở dữ liệu, và tốc độ đo là 20 giao dịch/giây trên cơ sở dữ liệu A và 80 trans/sec trên cơ sở dữ liệu B --- thì bạn sẽ biết rằng A đóng góp khoảng 20% ​​tổng CPU, và B đóng góp cho 80% khác.

Có một số sai sót ở đây, vì đó là giả định tất cả công việc đang được thực hiện là CPU bị ràng buộc, mà tất nhiên với cơ sở dữ liệu nó không. Nhưng đó sẽ là một khởi đầu tôi tin.

1

Tôi nghĩ câu trả lời cho câu hỏi của bạn là không.

Vấn đề là một hoạt động trên máy có thể gây tải trên nhiều cơ sở dữ liệu. Nếu tôi có một quá trình đọc từ một DB cấu ​​hình, đăng nhập vào một DB đăng nhập, và chuyển các giao dịch vào và ra khỏi các DB khác nhau dựa trên kiểu, làm cách nào để phân vùng sử dụng CPU?

Bạn có thể chia mức sử dụng CPU cho tải giao dịch, nhưng đó lại là một số liệu thô có thể đánh lừa bạn. Ví dụ, bạn sẽ phân chia vận chuyển nhật ký giao dịch từ một DB sang một DB khác như thế nào? Là tải CPU trong việc đọc hoặc viết?

Bạn nên xem xét tỷ lệ giao dịch cho máy và tải CPU gây ra. Bạn cũng có thể lập hồ sơ các thủ tục được lưu trữ và xem liệu có ai trong số họ đang dùng một lượng thời gian không đủ thời gian hay không; tuy nhiên, điều này sẽ không giúp bạn có được câu trả lời mà bạn muốn.

0

Hãy xem SQL Sentry. Nó làm tất cả những gì bạn cần và nhiều hơn nữa.

Kính trọng, Lieven

0

Bạn đã xem SQL profiler chưa?

Lấy mẫu "T-SQL" hoặc "Thủ tục lưu trữ" chuẩn, tinh chỉnh các trường để nhóm theo ID cơ sở dữ liệu (Tôi nghĩ bạn phải sử dụng số, bạn không nhận được tên cơ sở dữ liệu, nhưng dễ tìm sử dụng lệnh exec sp_databases để lấy danh sách)

Chạy ứng dụng này trong một thời gian và bạn sẽ nhận được tổng số CPU/Đĩa IO/Đợi, vv Điều này có thể cung cấp cho bạn tỷ lệ CPU được sử dụng bởi mỗi cơ sở dữ liệu.

Nếu bạn theo dõi bộ đếm PerfMon cùng một lúc (ghi dữ liệu vào cơ sở dữ liệu SQL), và làm tương tự cho SQL Profiler (đăng nhập vào cơ sở dữ liệu), bạn có thể có thể tương quan với nhau.

Mặc dù vậy, nó sẽ cung cấp cho bạn đủ đầu mối để xem DB nào đáng xem chi tiết hơn. Sau đó, làm lại một lần nữa với ID cơ sở dữ liệu đó và tìm kiếm thủ tục lưu trữ SQL/lưu trữ đắt nhất.

6

Đây là truy vấn sẽ hiển thị cơ sở dữ liệu thực tế gây tải cao. Nó dựa vào bộ nhớ cache truy vấn có thể bị xóa thường xuyên trong các tình huống bộ nhớ thấp (làm cho truy vấn ít hữu ích hơn).

select dbs.name, cacheobjtype, total_cpu_time, total_execution_count from 
    (select top 10 
     sum(qs.total_worker_time) as total_cpu_time, 
     sum(qs.execution_count) as total_execution_count, 
     count(*) as number_of_statements, 
     qs.plan_handle 
    from 
     sys.dm_exec_query_stats qs 
    group by qs.plan_handle 
    order by sum(qs.total_worker_time) desc 
    ) a 
inner join 
(SELECT plan_handle, pvt.dbid, cacheobjtype 
FROM (
    SELECT plan_handle, epa.attribute, epa.value, cacheobjtype 
    FROM sys.dm_exec_cached_plans 
     OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa 
    /* WHERE cacheobjtype = 'Compiled Plan' AND objtype = 'adhoc' */) AS ecpa 
PIVOT (MAX(ecpa.value) FOR ecpa.attribute IN ("dbid", "sql_handle")) AS pvt 
) b on a.plan_handle = b.plan_handle 
inner join sys.databases dbs on dbid = dbs.database_id 
0

hãy kiểm tra truy vấn này:

SELECT 
    DB_NAME(st.dbid) AS DatabaseName 
    ,OBJECT_SCHEMA_NAME(st.objectid,dbid) AS SchemaName 
    ,cp.objtype AS ObjectType 
    ,OBJECT_NAME(st.objectid,dbid) AS Objects 
    ,MAX(cp.usecounts)AS Total_Execution_count 
    ,SUM(qs.total_worker_time) AS Total_CPU_Time 
    ,SUM(qs.total_worker_time)/(max(cp.usecounts) * 1.0) AS Avg_CPU_Time 
FROM sys.dm_exec_cached_plans cp 
INNER JOIN sys.dm_exec_query_stats qs 
    ON cp.plan_handle = qs.plan_handle 
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st 
WHERE DB_NAME(st.dbid) IS NOT NULL 
GROUP BY DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid),cp.objtype,OBJECT_NAME(objectid,st.dbid) 
ORDER BY sum(qs.total_worker_time) desc 
1

Với tất cả đã nói ở trên trong tâm trí.
Bắt đầu với SQL Server 2012 (có thể là năm 2008?), có cột database_id trong sys.dm_exec_sessions.
Nó cho phép chúng tôi tính toán cpu dễ dàng cho từng cơ sở dữ liệu cho hiện đang kết nối phiên. Nếu phiên bị ngắt kết nối, thì kết quả của phiên đã biến mất.

select session_id, cpu_time, program_name, login_name, database_id 
    from sys.dm_exec_sessions 
where session_id > 50; 

select sum(cpu_time)/1000 as cpu_seconds, database_id 
from sys.dm_exec_sessions 
group by database_id 
order by cpu_seconds desc;