如何在Azure SQL Server主数据库查询中获取各Azure SQL数据库的逻辑CPU数量
如何在Azure SQL Server的master数据库中查询所有用户数据库的逻辑CPU数量?
我编写了一段需在master数据库运行的查询语句,用于概览Azure SQL Server下的所有Azure SQL数据库,现在希望在该查询中添加每个数据库的逻辑CPU数量字段。我知道可以在每个数据库单独执行查询获取该信息,但希望直接通过查询master数据库来获取所有数据库的逻辑CPU数量。请问是否可以通过sys系统视图获取该信息?还是只能使用动态SQL实现?
补充说明:有人建议使用
SELECT cpu_count FROM sys.dm_os_sys_info,但在master数据库中执行该语句只能看到master自身使用的CPU,我需要获取的是每个数据库的CPU使用数量。
核心结论
在Azure SQL Server的master数据库中,没有直接的系统视图能直接返回每个用户数据库的逻辑CPU数,但我们可以通过两种实用方式实现需求:
- 基于数据库的服务目标(Service Objective)推导CPU数量(适用于大多数固定层级的数据库)
- 使用动态SQL跨库查询每个数据库的
sys.dm_os_sys_info(适用于弹性池或需要实时准确值的场景)
方法1:通过服务目标推导CPU数量
Azure SQL数据库的逻辑CPU数和它的服务层级直接绑定:
- vCore模型:服务目标名称中包含明确的vCore数量(比如
GP_Gen5_8代表8个逻辑CPU) - DTU模型:不同DTU层级对应固定的逻辑CPU数(比如S0=1核、S1=2核、P1=4核等)
我已经帮你修改了原查询,加入CPU数量的计算逻辑:
DECLARE @StartDate date = DATEADD(day, -30, GETDATE()) -- 30 Days SELECT database_name AS DatabaseName, sysso.edition, sysso.service_objective, -- 计算逻辑CPU数量 CASE -- vCore模型:提取服务目标中的数字部分 WHEN sysso.service_objective LIKE '%_%_%' THEN TRY_CAST(RIGHT(sysso.service_objective, CHARINDEX('_', REVERSE(sysso.service_objective)) - 1) AS INT) -- DTU模型:映射固定CPU数 WHEN sysso.service_objective = 'S0' THEN 1 WHEN sysso.service_objective = 'S1' THEN 2 WHEN sysso.service_objective = 'S2' THEN 4 WHEN sysso.service_objective = 'S3' THEN 8 WHEN sysso.service_objective = 'P1' THEN 4 WHEN sysso.service_objective = 'P2' THEN 8 WHEN sysso.service_objective = 'P3' THEN 16 -- 其他DTU/特殊场景可自行补充映射规则 ELSE NULL END AS LogicalCPUCount, (SELECT TOP 1 storage_in_megabytes FROM sys.resource_stats AS rs2 WHERE rs2.database_name = rs1.database_name ORDER BY rs2.start_time DESC) AS StorageMB , CAST(MAX(storage_in_megabytes) / 1024 AS DECIMAL(10, 2)) StorageGB , MIN(end_time) AS StartTime ,MAX(end_time) AS EndTime , CAST(AVG(avg_cpu_percent) AS decimal(4,2)) AS Avg_CPU ,MAX(avg_cpu_percent) AS Max_CPU , (COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [CPU Fit %] , CAST(AVG(avg_data_io_percent) AS decimal(4,2)) AS Avg_IO ,MAX(avg_data_io_percent) AS Max_IO , (COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [Data IO Fit %] , CAST(AVG(avg_log_write_percent) AS decimal(4,2)) AS Avg_LogWrite ,MAX(avg_log_write_percent) AS Max_LogWrite , (COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [Log Write Fit %] FROM sys.resource_stats AS rs1 inner join sys.databases dbs on rs1.database_name = dbs.name INNER JOIN sys.database_service_objectives sysso on sysso.database_id = dbs.database_id WHERE start_time > @StartDate GROUP BY database_name, sysso.edition, sysso.service_objective ORDER BY database_name , sysso.edition, sysso.service_objective
注意:如果你的数据库使用弹性池(Elastic Pool),这种方法只能返回池的总CPU数,无法获取单个数据库的实际可用CPU,此时需要用方法2。
方法2:使用动态SQL跨库查询实时CPU数
如果需要获取每个数据库的实时逻辑CPU数(比如弹性池中的数据库),可以通过动态SQL遍历所有用户数据库,查询每个库的sys.dm_os_sys_info:
DECLARE @SQL NVARCHAR(MAX) = N''; -- 构建跨库查询语句 SELECT @SQL += N' UNION ALL SELECT ''' + name + ''' AS DatabaseName, cpu_count AS LogicalCPUCount FROM [' + name + '].sys.dm_os_sys_info' FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') -- 排除系统库 AND state_desc = 'ONLINE'; -- 只查在线数据库 -- 去掉第一个多余的UNION ALL SET @SQL = STUFF(@SQL, 1, 10, ''); -- 执行查询 EXEC sp_executesql @SQL;
你可以把这个动态SQL的结果和你的原查询做LEFT JOIN,就能把CPU数量整合到你的概览报表中。
总结
- 如果你的数据库都是固定层级的(非弹性池),方法1足够简单高效,不需要跨库访问
- 如果涉及弹性池或需要实时准确的CPU数,方法2是更可靠的选择
内容的提问来源于stack exchange,提问作者Francesco Mantovani
相关产品推荐
相关产品推荐

