为什么 运行 SQL Azure 上的查询要慢得多?

Why is running a query on SQL Azure so much slower?

我在 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 个不同服务器上的查询在我的枢轴 table 出现在屏幕上之前的运行时间方面给了我不同的结果:

Azure - 运行时间 = 100.165 秒

Smarterasp.net - 经过时间 = 2.449 秒

LocalServer - 运行时间 = 1.716 秒

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

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

我的问题是:

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

根据您的输入得出的结论:

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

谢谢大家, 卢锡安

(更新:原来的问题已经改成还问如何优化查询——这也是个好问题。原来的问题是为什么差异 这就是这个答案的内容)。

单个查询的性能受性能层的影响很大。我知道文档暗示层级与负载有关,但严格来说并非如此。

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

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

即使在 S1 和 S2 之间移动,单个查询的性能也会有显着差异。 如果你想做实验,请记住你需要支付 "any part of a day" 一天的费用,这对 S 级来说可能没问题,但在测试 P 级时要小心。

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

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

更新后

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

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

这是你应该做的:

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

下面是如何参数化内部 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 支持可更新的聚集列存储索引,您可以在预期数据量很大的情况下进行试验。他们确实需要 Enterprise/Development 在本地框上,是的。

这与您的帐户是试用版无关,这是因为您选择的性能级别较低。

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

在这一点上,不可能将 DTU 的实际含义放在一起/哪种 DTU 编号与安装在本地计算机或任何其他托管服务提供商中的 Sql 服务器相关联。

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