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

Luc*_*umb 24 sql ssms azure sql-server-2014 azure-sql-database

我在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
Run Code Online (Sandbox Code Playgroud)

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

Azure - 经过的时间= 100.165秒

Smarterasp.net - 经过的时间= 2.449秒

LocalServer - 经过的时间= 1.716秒

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

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

我的问题是:

  1. 我该怎么做才能优化这个查询(sp)?
  2. Azure建议用于小型数据库(100mb-1Gb)吗?我的意思是性能与成本!

结论基于您的输入:

  • 我对查询进行了建议更改,性能提高了50%以上 - 谢谢Remus
  • 我在Azure S2上测试了我的查询,更新查询的经过时间是11秒.
  • 我再次测试了我对P1的查询,经过的时间是0.5秒:)

  • SmarterASP上相同的更新查询已经过了0.8秒的时间.

现在很清楚Azure中的层是什么,有一个非常好的查询是多么重要(我甚至理解什么是索引和他的优势/劣势)

谢谢大家,卢西恩

Fra*_*ans 13

(更新:原来的问题已被更改为也询问如何优化查询 - 这也是一个很好的问题.最初的问题是为什么这个答案的差异是什么).

各个查询的性能受性能层的严重影响.我知道文档暗示层是关于加载的,这不是严格正确的.

我会以S2数据库作为起点重新运行您的测试并从那里开始.

试用订阅本身并不会影响性能,但是对于免费帐户,您可能正在使用B级别,而这种级别实际上并不是真正可用 - 当然不适用于本地运行需要2秒钟的查询.

即使在S1和S2之间移动,也会在单个查询的性能上显示出明显的差异.如果你想进行实验,请记住你每天都要收取"一天中的任何一部分"的费用,这对于S级来说可能没问题,但在测试P级时要小心.

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

  • 您对具有任何类型性能差异的试用帐户的断言是**完全错误**.使用试用帐户的服务性能绝对不同,我甚至不知道您收到此信息的位置.此外,您将对"SQL数据库服务"的实现方式进行"猜测". (2认同)
  • 我在生产中有超过100个sql azure数据库,并通过大量测试证实了这一点.我也直接由微软内部的人员确认了这一点.如果你读了我的答案 (2认同)
  • 您声明从试用订阅分配的数据库的性能低于付费订阅的数据库.这是不真实的. (2认同)

Rem*_*anu 13

这首先是性能问题.您正在处理性能不佳的代码,您必须确定瓶颈并解决它.我现在正在谈论糟糕的2秒表现.请遵循如何分析SQL Server性能的准则.一旦您将此查询执行到本地可接受的Web应用程序(少于5毫秒),您就可以询问将其移植到Azure SQL DB的问题.目前,您的试用帐户仅突出显示现有的低效率.

更新后

...
@iddepartment int
...
iddepartment='+convert(nvarchar(max),@iddepartment)+'
...
Run Code Online (Sandbox Code Playgroud)

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

这是你应该做的:

  • @iddepartment在内部动态SQL中进行参数化
  • 停止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;
Run Code Online (Sandbox Code Playgroud)

到目前为止,覆盖索引是最重要的修复.这显然需要比现在更多的信息.阅读设计索引,包括所有子章节.

作为一个更普遍的评论:这种查询BEFIT columnstores比rowstore多,虽然我估计数据大小,基本上,微小.Azure SQL DB支持可更新的群集列存储索引,您可以在预测严重数据大小的情况下对其进行试验.他们确实需要在本地方框上进行企业/开发,这是真的.

  • @remus - 这是一个很好的评论,但它不是一个答案; 这是一个做一些分析和发布更好问题的建议. (5认同)
  • @DavidMakogon我真的认为这是一个答案,而不是评论.在他考虑选择Azure SLO之前,Lucian确实需要首先关注应用程序的性能.回答*为什么*是他现在选择的SLO比无约束的独立实例慢得多,因为我很确定他不能简单地选择PXX并让应用程序保持原样. (3认同)