简体   繁体   English

Azure SQL数据库 - 查询速度明显慢于Azure VM上的SQL数据库

[英]Azure SQL Database - queries significantly slower than SQL Database on Azure VM

We moved our SQL Server from an Azure VM to an Azure SQL Database. 我们将SQL Server从Azure VM移动到Azure SQL数据库。 The Azure VM was DS2_V2, 2 core, 7GB RAM, 6400 max IOPS The Azure SQL Database is Standard S3, 100 DTU. Azure VM是DS2_V2,2核,7GB RAM,最大6400 IOPS Azure SQL数据库是标准S3,100 DTU。 I chose this tier after running the Azure DTU Calculator tool on the Azure VM for 24 hours - it suggested this tier for me. 我在Azure VM上运行Azure DTU计算器工具24小时后选择了这个层 - 它为我建议了这个层。

The problem is that queries (mostly SELECT and UPDATE) are painfully slow now, compared to how they were on the Azure VM. 问题是,与Azure VM上的查询相比,查询(主要是SELECT和UPDATE)现在非常缓慢。 One thing I noticed is that while running a query, I went to the Resource Utilization graph under Monitoring in the Azure Portal, and it's pinging 100% throughout the time any query is being run. 我注意到的一件事是,在运行查询时,我访问了Azure门户中的“监控”下的“资源利用率”图,并且在运行任何查询的整个过程中它都是100%ping。 Does this mean my tier is in fact too low? 这是否意味着我的等级实际上太低了? I would hope not because the next tier up is a pretty big jump in cost. 我希望不会因为下一阶段的成本上涨相当大。

Just for information, the Azure SQL Database is identical in schema and data to the Azure VM database, and I rebuilt all indexes (including Full-Text) after the migration. 仅供参考,Azure SQL数据库的架构和数据与Azure VM数据库完全相同,我在迁移后重建了所有索引(包括全文)。

In my research thus far I've read everything from making sure my Azure SQL DB is in the right region on Azure (it is) to network latency (non-existent on Azure VM) causing the issue. 到目前为止,在我的研究中,我已经阅读了从确保我的Azure SQL数据库在Azure上的正确区域(它)到网络延迟(Azure VM上不存在)导致此问题的所有内容。

How long has this system been running now as an Azure SQL Server Database? 该系统现在作为Azure SQL Server数据库运行了多长时间? Presumably if it's more than a few hours old (ie some "production" queries have hit it) and it's generated some useful statistics. 据推测,如果它超过几个小时(即一些“生产”查询已经命中它)并且它产生了一些有用的统计数据。

Analyzing this and determining the source of your problem will be a multi-pronged strategy . 分析这个并确定问题的根源将是一个多管齐下的策略

Service Tier Check 服务层检查

Try the following queries, which determine whether you are at the correct service level: 请尝试以下查询,以确定您是否处于正确的服务级别:

-----------------------
---- 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

Resource Consumption Levels 资源消耗水平

It would also be useful to check the resource consumption, which you can do using the following query. 检查资源消耗也很有用,您可以使用以下查询来执行此操作。 This will report things like DTU consumption and IO. 这将报告DTU消耗和IO等内容。

-----------------
-- Resource Usage
-----------------
select *
from sys.dm_db_resource_stats 
order by end_time desc

Indexes 索引

It's also worth a quick check whether you have missing indexes or whether some of your existing indexes are getting in the way. 还值得快速检查一下您是否缺少索引或是否有一些现有索引妨碍了。

The missing index query is a doozy, but should be taken with a grain of salt. 丢失的索引查询是一个doozy,但应该采取一些盐。 I generally see it as an advisement on how the db is being used and I make my own judgement on which indexes to add, and how. 我通常将其视为关于如何使用数据库的建议,并且我自己判断要添加哪些索引以及如何添加。 For example, as a general rule of thumb, all foreign keys should have non-clustered indexes to facilitate the inevitable JOIN's they're involved in. 例如,作为一般经验法则,所有外键都应该具有非聚集索引,以便于它们参与的不可避免的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

Maintenance 保养

A maintenance plan should also be setup, whereby you are rebuilding indexes and statistics on a somewhat regular basis. 还应设置维护计划,以便您定期重建索引和统计信息。 Unfortunately there is no SQL Agent in an Azure SQL environment. 遗憾的是,Azure SQL环境中没有SQL代理。 But Powershell and either an Azure function or Azure WebJob can help you schedule and execute this. 但是Powershell和Azure功能Azure WebJob可以帮助您安排和执行此功能。 For our on-prem and azure servers, we do this weekly. 对于我们的本地和天蓝色服务器,我们每周都会这样做。

Note that WebJob's would only help if you have a pre-existing App Service to run it within. 请注意,只有拥有预先存在的App Service才能在其中运行WebJob。

For scripts on helping you with index and statistics maintenance, checkout Ola Hallengren's script offering. 有关帮助您进行索引和统计信息维护脚本,请查看Ola Hallengren的脚本产品。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM