如何查看服务器上哪个数据库使用的资源最多

Mat*_*s F 4 performance sql-server-2008 sql-server

我有一个数据库服务器,上面有几个数据库。我如何才能看到任何资源压力可能来自哪里?

我想得到一张表:

  • 数据库名称
  • 每秒批处理请求数
  • CPU时间
  • 逻辑读取
  • 逻辑写入

Rem*_*anu 10

只有某些资源可以跟踪到数据库。IO 和缓冲池使用情况可以清楚地跟踪到数据库:

查询执行统计(如逻辑读取)可以归因于查询,但不能(正确)与数据库关联,因为查询可以(并且经常)跨越数据库。sys.dm_exec_query_stats是这些统计数据的主要入口点。


swa*_*eck 9

我已经将这个查询与其他一些查询拼凑在一起。这并不完全是您要查找的内容,但可以让您了解您可能正在查看的资源消耗类型。

    DECLARE @total_buffer INT;
    SELECT  @total_buffer = cntr_value
        FROM sys.dm_os_performance_counters
        WHERE RTRIM([object_name]) LIKE '%Buffer Manager'
            AND (counter_name = 'Total Pages' --this is 2008
            OR counter_name = 'Database pages'); -- this is 2012
    ;WITH src AS (
        SELECT
            database_id, DB_Buffer_Pages = COUNT_BIG(*)
            FROM sys.dm_os_buffer_descriptors
            --WHERE database_id BETWEEN 5 AND 32766
            GROUP BY database_id
        )

    SELECT 
        database_name = DB_NAME(mem.database_id), 
        db_buffer_pages, 
        cached_size_mb,
        db_buffer_pct, 
        cpu_time, 
        cpu_percent_usage, 
        total_io_mb, 
        io_percent          
    FROM (

            --DatabaseName = CASE [database_id] WHEN 32767
            --              THEN 'Resource DB'
            --              ELSE DB_NAME([database_id]) END,
            SELECT
            database_id,
            db_buffer_pages = DB_Buffer_Pages,
            cached_size_mb = DB_Buffer_Pages / 128.0,
            db_buffer_pct = CONVERT(DECIMAL(6,3),
                                DB_Buffer_Pages * 100.0 / @total_buffer)        
            FROM src
        ) mem
        JOIN (
                SELECT 
                    database_id, cpu_time, 
                    CAST(cpu_time * 1.0 / SUM(cpu_time) OVER() * 100.0 AS DECIMAL(5, 2)) AS cpu_percent_usage
                FROM (
                        SELECT database_id, SUM(total_worker_time) AS cpu_time
                        FROM sys.dm_exec_query_stats AS qs
                        CROSS APPLY (SELECT CONVERT(int, value) AS database_id 
                                        FROM sys.dm_exec_plan_attributes(qs.plan_handle)
                                        WHERE attribute = N'dbid') AS F_DB
                        GROUP BY database_id) DB_CPU_Stats
        ) cpu
            ON mem.database_id = cpu.database_id
        JOIN (
                SELECT database_id, io_in_mb AS [total_io_mb],
                    CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [io_percent]
                FROM (
                        SELECT database_id,
                            CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb
                        FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
                        GROUP BY database_id) Aggregate_IO_Statistics) [io]
        ON mem.database_id = [io].database_id  
Run Code Online (Sandbox Code Playgroud)

这里有一些东西可以让你了解读取和写入的信息(从其他一些查询中拼凑而成):

CREATE TABLE #results
(
    DatabaseName SYSNAME ,
    VLFcount INT
);
--  Create the SQL Server 2012-compatible table. We'll drop the column if it's not 2012
CREATE TABLE #stage
(
    RecoveryUnitId INT ,
    FileID INT ,
    FileSize BIGINT ,
    StartOffset BIGINT ,
    FSeqNo BIGINT ,
    [Status] BIGINT ,
    Parity BIGINT ,
    CreateLSN NUMERIC(38)
);
BEGIN TRY  
    INSERT INTO #stage 
    EXECUTE sp_executesql N'DBCC LOGINFO()';                
    -- if it worked then we don't want this data twice
    TRUNCATE TABLE #stage;
END TRY
BEGIN CATCH
    --All versions between 2000 and 2008R2 do not have RecoveryUnitId
    ALTER TABLE #stage
        DROP COLUMN RecoveryUnitId;         
END CATCH 
EXECUTE sp_msforeachdb N'Use [?]; 
                            INSERT INTO #stage 
                            EXECUTE sp_executesql N''DBCC LOGINFO([?])''; 

                            INSERT INTO #results 
                            SELECT DB_Name(), COUNT(*) 
                            FROM #stage; 
                            TRUNCATE TABLE #stage;' 
SELECT  
    collection_date =  SYSDATETIME(),--COALESCE(@CollectionDate, GETDATE()),
    file_type = CASE vfs.file_id WHEN 2 THEN 'Log' ELSE 'Data' END,
    database_name = DB_NAME(vfs.database_id), 
    mf.physical_name, 
    io_stall_read_ms, 
    num_of_reads,
    avg_read_stall_ms = CAST(io_stall_read_ms/(1.0 + num_of_reads) AS NUMERIC(10,1)),
    pct_read_stall = CAST(100. * vfs.io_stall_read_ms/(vfs.io_stall_read_ms + vfs.io_stall_write_ms) AS DECIMAL(10,1)),
    pct_num_reads = CAST(100. * vfs.num_of_reads/(vfs.num_of_reads + vfs.num_of_writes) AS DECIMAL(10,1)),
    pct_read_bytes = CAST(100. * vfs.num_of_bytes_read/(vfs.num_of_bytes_read + vfs.num_of_bytes_written) AS DECIMAL(10,1)),
    io_stall_write_ms, 
    num_of_writes,
    avg_write_stall_ms = CAST(io_stall_write_ms/(1.0+num_of_writes) AS NUMERIC(10,1)),
    pct_write_stall = CAST(100. * vfs.io_stall_write_ms/(vfs.io_stall_write_ms + vfs.io_stall_read_ms) AS DECIMAL(10,1)),
    pct_num_writes = CAST(100. * vfs.num_of_writes/(vfs.num_of_reads + vfs.num_of_writes) AS DECIMAL(10,1)),
    pct_write_bytes = CAST(100. * vfs.num_of_bytes_written/(vfs.num_of_bytes_read + vfs.num_of_bytes_written) AS DECIMAL(10,1)),
    io_stalls = io_stall_read_ms + io_stall_write_ms, 
    total_io = num_of_reads + num_of_writes,
    avg_io_stall_ms = CAST((io_stall_read_ms + io_stall_write_ms)/(1.0 + num_of_reads + num_of_writes) AS NUMERIC(10,1)),
    io_stall, 
    size_on_disk_bytes, 
    vlf = VLFcount              
FROM sys.dm_io_virtual_file_stats(null,null) AS vfs
    INNER JOIN sys.master_files AS mf 
        ON vfs.database_id = mf.database_id
            AND vfs.[file_id] = mf.[file_id]
    INNER JOIN #results vlf
        ON DB_NAME(vfs.database_id) = vlf.DatabaseName;  
drop table #stage;
drop table #results;
Run Code Online (Sandbox Code Playgroud)

请注意,此处适用的警告与 Remus 的回答相同。此外,这些信息中的大部分作为一次性信息是无用的,更适合随着时间的推移进行评估。

  • 你应该写博客。 (2认同)