为啥在 SQL Azure 上运行查询要慢得多?

Posted

技术标签:

【中文标题】为啥在 SQL Azure 上运行查询要慢得多?【英文标题】:Why is running a query on SQL Azure so much slower?为什么在 SQL Azure 上运行查询要慢得多? 【发布时间】:2015-09-14 05:02:56 【问题描述】:

我在Azure 上创建了一个试用帐户,并从SmarterAsp 部署了我的数据库。

当我对SmarterAsp\MyDatabase 运行数据透视查询时,结果会在 2 秒内出现。

但是,在 Azure\MyDatabase 上运行相同的查询需要 94 秒

我使用 SQL Server 2014 Management Studio(试用版)连接到服务器并运行查询。

这种速度差异是因为我的帐户是试用帐户吗?

我的问题的一些相关信息

查询是:

ALTER procedure [dbo].[Pivot_Per_Day]
@iyear int,
@imonth int,
@iddepartment int

as

declare @columnName Nvarchar(max) = ''
declare @sql Nvarchar(max) =''

select @columnName += quotename(iDay) + ','
from (
        Select day(idate) as iDay
        from kpivalues where year(idate)=@iyear and month(idate)=@imonth
        group by idate
        )x

set @columnName=left(@columnName,len(@columnName)-1)

set @sql ='


Select * from (
select kpiname, target, ivalues, convert(decimal(18,2),day(idate)) as iDay   

from kpi

inner join kpivalues on kpivalues.idkpi=kpi.idkpi

inner join kpitarget on kpitarget.idkpi=kpi.idkpi

inner join departmentbscs on departmentbscs.idkpi=kpi.idkpi

where iddepartment='+convert(nvarchar(max),@iddepartment)+'

group by kpiname,target, ivalues,idate)x

pivot
(
     avg(ivalues)
    for iDay in (' + @columnName + ')
) p'

execute sp_executesql @sql

在 3 个不同的服务器上运行此查询在我的数据透视表出现在屏幕上之前的经过时间方面给了我不同的结果:

Azure - 已用时间 = 100.165 秒

Smarterasp.net - 经过时间 = 2.449 秒

LocalServer - 经过的时间 = 1.716 秒

关于我在 Azure 上的试用帐户,我的主要目标是检查运行上述存储过程时我是否会比 Smarter 有更好的速度。 我为我的数据库选择服务层 - 基本、性能级别 - 基本(5DTU)和最大。大小 2GB。

我的数据库有16个表,1个表有145284行,数据库大小是11mb。它是我的应用程序的测试数据库。

我的问题是:

    我可以做些什么来优化这个查询 (sp)? 是否建议将 Azure 用于小型数据库 (100mb-1Gb)?我的意思是性能与成本!

根据您的意见得出的结论:

我对查询进行了建议的更改,性能提高了 50% 以上 - 谢谢 Remus 我在 Azure S2 上测试了我的查询,更新查询的经过时间为 11 秒。

我在 P1 上再次测试了我的查询,经过的时间是 0.5 秒 :)

SmarterASP 上相同的更新查询已用时 0.8 秒。

现在我很清楚 Azure 中有哪些层以及拥有一个非常好的查询有多重要(我什至了解什么是索引以及他的优势/劣势)

谢谢大家, 卢锡安

【问题讨论】:

这不是你应该问 Azure 支持的问题吗?我们应该如何知道您的帐户及其设备的详细信息? 您是在谈论 SQL Azure 吗?性能非常依赖于层。小于 S2 的任何东西都不太可能给您可接受的性能。不,它不依赖于负载,单个查询性能受到层级的严重影响。 @Lucian - 就您的问题而言,这完全不清楚。您没有在问题中显示任何 SQL 查询,也没有提到有关本地服务器或所选 SQL 数据库层的任何事情。也就是说:如果是关于服务器性能(或层性能),那是 ServerFault 的问题,而不是 *** 的问题。如果是查询问题,那么它适用于 ***,但不作为不同服务层/托管公司之间的性能差异。 为 Lucian 的问题辩护,不同 SQL Azure 数据库层的性能之间存在非常明显的差异。价格/性能比的增长速度快于线性增长,因此了解这一点对于应用程序设计非常重要,因为分片和缓存等决策通常由价格和性能相关的方式驱动。我最近不止一次发生过这种情况。需要明确的是,我是 SQL Azure 的忠实粉丝——我在 Azure 中有 100 多个生产数据库。我也认为价格很有竞争力——但理解这一点对于设计来说是必不可少的。 @lucian;按照您的编辑进行澄清;这是因为基本性能级别。根据我在下面的回答,尝试将 S2 作为更现实的起始级别。值得一次尝试所有级别,性能差异很大。 【参考方案1】:

这首先是一个性能问题。您正在处理性能不佳的代码,您必须确定瓶颈并解决它。我现在说的是糟糕的 2 秒 性能。遵循How to analyse SQL Server performance 的指导方针。一旦让这个查询在本地执行 Web 应用程序可接受(少于 5 毫秒),您就可以提出将其移植到 Azure SQL DB 的问题。目前,您的试用帐户只是突出了现有的低效率。

更新后

...
@iddepartment int
...
iddepartment='+convert(nvarchar(max),@iddepartment)+'
...

那是什么? iddepartment 列是 int 还是 nvarchar?为什么要使用(max)

这是你应该做的:

在内部动态SQL中参数化@iddepartment 停止进行nvarchar(max) 转换。使 iddepartment@iddertment 类型匹配 确保iddepartment 和所有idkpis 上的索引

下面是如何参数化内部 SQL:

set @sql =N'
Select * from (
select kpiname, target, ivalues, convert(decimal(18,2),day(idate)) as iDay   
from kpi
inner join kpivalues on kpivalues.idkpi=kpi.idkpi
inner join kpitarget on kpitarget.idkpi=kpi.idkpi
inner join departmentbscs on departmentbscs.idkpi=kpi.idkpi
where iddepartment=@iddepartment
group by kpiname,target, ivalues,idate)x
pivot
(
     avg(ivalues)
    for iDay in (' +@columnName + N')
) p'

execute sp_executesql @sql, N'@iddepartment INT', @iddepartment;

到目前为止,覆盖索引是最重要的修复。这显然需要比这里更多的信息。阅读Designing Indexes,包括所有子章节。

作为更一般的评论:这种查询比行存储更适合columnstores,尽管我认为数据大小基本上很小。 Azure SQL DB 支持可更新的聚集列存储索引,您可以在预期严重的数据大小时对其进行试验。他们确实需要在本地机器上进行企业/开发,没错。

【讨论】:

是的,我的查询肯定可以优化,我是初学者,我所做的只是在互联网上搜索“如何...?” :) @remus - 这是一个很好的评论,但这不是一个答案;这是进行一些分析并发布更好问题的建议。 @DavidMakogon 我真的认为这是一个答案,而不是评论。在考虑选择 Azure SLO 之前,Lucian 确实需要首先专注于让应用程序运行。回答 为什么 是他现在选择的任何 SLO 都比无约束的独立实例慢得多,因为我很确定他不能简单地选择 PXX 并让应用保持原样。跨度> 【参考方案2】:

(更新:原来的问题已更改为还询问如何优化查询 - 这也是一个很好的问题。原来的问题是为什么会有差异这就是这个答案的目的)。

单个查询的性能受性能层的影响很大。我知道文档暗示这些层是关于负载的,这并不完全正确。

我会以 S2 数据库为起点重新运行您的测试,然后从那里开始。

试用订阅本身并不会影响性能,但对于免费帐户,您可能使用的是 B 级,这对于任何真实的东西都不能真正使用 - 当然不适用于需要 2 秒在本地运行的查询。

即使在 S1 和 S2 之间移动也会显示单个查询的性能存在显着差异。 如果您想进行实验,请记住“一天中的任何部分”都按天收费,这对于 S 级可能是可以的,但在测试 P 级时要小心。

用于背景;当 Azure 去年推出新层时,他们改变了 SQL 的托管模型。过去,许多数据库将在共享的 sqlserver.exe 上运行。在新模型中,每个数据库都有效地获得了自己的 sqlserver.exe,它在资源受限的沙箱中运行。这就是他们控制“DTU 使用”的方式,但也会影响总体性能。

【讨论】:

您关于试用帐户存在任何类型的性能差异的断言完全错误。试用帐户的服务性能绝对为零,我什至不知道您从哪里收到这些信息。此外,您正在“猜测” SQL 数据库服务是如何在幕后实现的。 我在生产中拥有超过 100 个 sql azure 数据库,并通过广泛的测试证实了这一点。我也得到了微软内部实际从事此工作的人员的直接确认。如果您在中阅读了我的回答 关于试用帐户:作为一名每天使用 Azure 的 Microsoft 员工,您告诉我一些我从未听说过的事情。永远。 ... 我指的是不同的数据库层,我假设他在测试中使用了 B 层。一定要进行自己的测试,你就会明白我的意思。 您是说从试用订阅分配的数据库的性能低于付费订阅的数据库。这是不真实的。【参考方案3】:

这与您的帐户处于试用状态无关,这是由于您选择的性能级别较低。

在其他服务 (SmarterAsp) 和运行本地实例中,您可能没有性能限制,而是大小限制。

此时,无法将 DTU 的实际含义/哪种类型的 DTU 编号与安装在本地计算机或任何其他托管服务提供商中的 Sql 服务器相关联。

但是,对此进行了一些很好的分析 (https://cbailiss.wordpress.com/2014/09/16/performance-in-new-azure-sql-database-performance-tiers/),但没有任何官方的。

【讨论】:

以上是关于为啥在 SQL Azure 上运行查询要慢得多?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Python 3 中未编译的、重复使用的正则表达式要慢得多?

为啥在 SQL 查询中 NOT IN 比 IN 慢得多

对于非常接近零的值,双重计算运行速度要慢得多

几乎相同的代码运行速度要慢得多

String.replaceAll 比自己完成工作要慢得多

为啥通过 django QuerySet 进行查询比在 Django 中使用游标慢得多?