Stp*_*111 5 sql-server azure azure-virtual-machine azure-sql-database
我们将SQL Server从Azure VM移动到Azure SQL数据库.Azure VM是DS2_V2,2核,7GB RAM,最大6400 IOPS Azure SQL数据库是标准S3,100 DTU.我在Azure VM上运行Azure DTU计算器工具24小时后选择了这个层 - 它为我建议了这个层.
问题是,与Azure VM上的查询相比,查询(主要是SELECT和UPDATE)现在非常缓慢.我注意到的一件事是,在运行查询时,我访问了Azure门户中的"监控"下的"资源利用率"图,并且在运行任何查询的整个过程中它都是100%ping. 这是否意味着我的等级实际上太低了?我希望不会因为下一阶段的成本上涨相当大.
仅供参考,Azure SQL数据库的架构和数据与Azure VM数据库完全相同,我在迁移后重建了所有索引(包括全文).
到目前为止,在我的研究中,我已经阅读了从确保我的Azure SQL数据库在Azure上的正确区域(它)到网络延迟(Azure VM上不存在)导致此问题的所有内容.
这个系统现在作为 Azure SQL Server 数据库运行多久了?据推测,如果它超过几个小时(即一些“生产”查询已经命中它)并且它生成了一些有用的统计数据。
分析这一点并确定问题的根源将是一个多管齐下的策略。
尝试以下查询,以确定您是否处于正确的服务级别:
-----------------------
---- SERVICE TIER CHECK
-----------------------
-- The following query outputs the fit percentage per resource dimension, based on a threshold of 20%.
-- IF the query below returns values greater than 99.9 for all three resource dimensions, your workload is very likely to fit into the lower performance level.
SELECT
(COUNT(end_time) - SUM(CASE WHEN avg_cpu_percent >= 20 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'CPU Fit Percent'
,(COUNT(end_time) - SUM(CASE WHEN avg_log_write_percent >= 20 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'Log Write Fit Percent'
,(COUNT(end_time) - SUM(CASE WHEN avg_data_io_percent >= 20 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'Physical Data Read Fit Percent'
FROM sys.dm_db_resource_stats
-- Look at how many times your workload reaches 100% and compare it to your database workload SLO.
-- IF the query below returns a value less than 99.9 for any of the three resource dimensions, you should consider either moving to the next higher performance level or use application tuning techniques to reduce the load on the Azure SQL Database.
SELECT
(COUNT(end_time) - SUM(CASE WHEN avg_cpu_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'CPU Fit Percent'
,(COUNT(end_time) - SUM(CASE WHEN avg_log_write_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'Log Write Fit Percent'
,(COUNT(end_time) - SUM(CASE WHEN avg_data_io_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(end_time) AS 'Physical Data Read Fit Percent'
FROM sys.dm_db_resource_stats
Run Code Online (Sandbox Code Playgroud)
检查资源消耗也很有用,您可以使用以下查询进行检查。这将报告诸如 DTU 消耗和 IO 之类的内容。
-----------------
-- Resource Usage
-----------------
select *
from sys.dm_db_resource_stats
order by end_time desc
Run Code Online (Sandbox Code Playgroud)
还值得快速检查一下您是否缺少索引,或者您的某些现有索引是否妨碍了您的工作。
缺失的索引查询很糟糕,但应该持保留态度。我通常将其视为关于如何使用数据库的建议,并且我自己判断要添加哪些索引以及如何添加。例如,作为一般经验法则,所有外键都应该具有非聚集索引,以促进它们所涉及的不可避免的 JOIN。
--------------------
-- Find poor indexes
--------------------
DECLARE @dbid int
SELECT @dbid = db_id()
SELECT 'Table Name' = object_name(s.object_id), 'Index Name' =i.name, i.index_id,
'Total Writes' = user_updates, 'Total Reads' = user_seeks + user_scans + user_lookups,
'Difference' = user_updates - (user_seeks + user_scans + user_lookups)
FROM sys.dm_db_index_usage_stats AS s
INNER JOIN sys.indexes AS i
ON s.object_id = i.object_id
AND i.index_id = s.index_id
WHERE objectproperty(s.object_id,'IsUserTable') = 1
AND s.database_id = @dbid
AND user_updates > (user_seeks + user_scans + user_lookups)
ORDER BY 'Difference' DESC, 'Total Writes' DESC, 'Total Reads' ASC;
------------------
-- Missing Indexes
------------------
declare @improvementMeasure int = 100
SELECT
CONVERT (decimal (28,1),
migs.avg_total_user_cost *
migs.avg_user_impact *
(migs.user_seeks + migs.user_scans))
AS improvement_measure,
OBJECT_NAME(mid.object_id, mid.database_id) as table_name,
mid.equality_columns as index_column,
mid.inequality_columns,
mid.included_columns as include_columns,
'CREATE INDEX IX_' +
OBJECT_NAME(mid.object_id, mid.database_id) +
'_' +
REPLACE(REPLACE(mid.equality_columns, '[', ''), ']', '') +
' ON ' +
mid.statement +
' (' + ISNULL (mid.equality_columns,'') +
CASE WHEN mid.equality_columns IS NOT NULL
AND mid.inequality_columns IS NOT NULL
THEN ','
ELSE ''
END + ISNULL (mid.inequality_columns, '') +
')' +
ISNULL (' INCLUDE (' + mid.included_columns + ')',
'') AS create_index_statement,
migs.user_seeks,
migs.unique_compiles,
migs.avg_user_impact,
migs.avg_total_user_cost
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid
ON mig.index_handle = mid.index_handle
WHERE CONVERT (decimal (28,1),
migs.avg_total_user_cost *
migs.avg_user_impact *
(migs.user_seeks + migs.user_scans)) > @improvementMeasure
ORDER BY migs.avg_total_user_cost *
migs.avg_user_impact *
(migs.user_seeks + migs.user_scans) DESC
Run Code Online (Sandbox Code Playgroud)
还应制定维护计划,以便您定期重建索引和统计信息。不幸的是,Azure SQL 环境中没有 SQL 代理。但是 Powershell 和Azure 函数或Azure WebJob可以帮助您安排和执行此操作。对于我们的本地和 azure 服务器,我们每周执行一次。
请注意,WebJob 仅在您有一个预先存在的应用服务来运行它时才有帮助。
有关帮助您进行索引和统计维护的脚本,请查看 Ola Hallengren 的脚本产品。