SQL Server的全表扫描和负载

问题描述:

对于这个问题的目的,让我们假装我有如下表:SQL Server的全表扫描和负载

交易

  • 编号
  • 产品编号
  • 产品名称
  • 城市
  • 国家
  • UnitCost
  • SellAmount
  • NumberOfTimesPurchased
  • 利润(NumberOfTimesPurchased *(SellAmount - UnitCost))

基本上,在一百万加行的单一反规范化的表。需要注意的是,只有两列会更新:Profit和NumberOfTimesPurchased。进行销售时,购买的NumberOfTimes将更新,新的利润金额将重新计算。

现在,我需要对此表进行一些最小化的报告,该报告由聚合和分组查询组成。举例:

SELECT 
    City, AVG(UnitCost), AVG(SellAmount), 
    SUM(NumberOfTimesPurchased), AVG(Profit) 
FROM 
    Transaction 
GROUP BY 
    City 

SELECT 
    State, AVG(UnitCost), AVG(SellAmount), SUM(NumberOfTimesPurchased), 
    AVG(Profit) 
FROM 
    Transaction 
GROUP BY 
    State 

SELECT 
    Country, AVG(UnitCost), AVG(SellAmount), SUM(NumberOfTimesPurchased), 
    AVG(Profit) 
FROM 
    Transaction 
GROUP BY 
    Country 

SELECT 
    ProductId, ProductName, AVG(UnitCost), AVG(SellAmount), 
    SUM(NumberOfTimesPurchased), AVG(Profit) 
FROM 
    Transaction 
GROUP BY 
    ProductId, ProductName 

这些查询很快:〜1秒。但是,我注意到,在负载下,性能显着下降(当有20个并发请求时,性能显着下降(从1秒到1分钟),而我是猜测原因是每个查询都执行全表扫描。

我试图为每个查询使用索引视图,但是由于每个视图需要重建,所以我的更新语句的性能需要跳动。在同样的说明中,我试图为每个查询创建覆盖索引,但是我的更新语句性能再次不能被接受。

假设全表扫描是罪魁祸首,我是否有任何实际的选择来缩短查询时间,同时保持更新性能在可接受的水平?

请注意,我不能使用列存储索引(我使用的是更便宜的Azure SQL数据库版本)。我还想远离任何形式的汇总实施,因为我需要立即提供数据。

最后 - 上面的例子不是我的表的完全准确的表示。我有20个左右不同的列可以“分组”,6列可以更新。没有插入或删除。

由于查询中没有WHERE子句,数据库引擎只能执行表扫描(或聚簇索引扫描,它实际上是同一件事)。如果覆盖了包含查询中所有列的索引,那么引擎会优先选择这些列。如果您的真实查询具有WHERE子句,那么将这些列作为索引的前导列进行适当索引可能会对有所帮助。

但我认为你的问题在别处。就并发性而言,你没有投入足够的钱。据主service tiers文档,为Azure的SQL数据库的基本层是:

...在给定时间通常一个单一 积极运作支持。示例包括用于开发或测试的数据库或小规模不常使用的应用程序。

因此,您可能需要考虑花费高级版来支持您的并发需求和列存储索引,它们非常适合这种类型的查询。为了好玩,我创建了一个基于AdventureWorksDW2012的测试平台,试图重现您的问题,即here。查询性能非常糟糕(> 20秒)。我会感到惊讶,如果你不是在您的门户网站越来越DTU警告:

DTU Warnings

升级到标准(S0-S2)确实提高性能所以你应该尝试。您可以考虑扩大繁忙查询时间,并在不需要时关闭。

该表格看起来有点像事实表,所以您可能需要考虑将其重构为事实/维度模型,然后在顶部使用Azure Analysis Services来实现该亚秒级性能。

巧合的是有你可以投票,使列存储到标准层反馈项目:

https://feedback.azure.com/forums/217321-sql-database/suggestions/6878001-make-sql-column-store-feature-available-for-standa

最近的评论表明,它是“在工作队列”截至2017年5月;

+1

对于这个应用程序,初始查询被认为是未过滤的,所以不会有'WHERE'子句(然而后续的查询可能有它们)。 我一直在收到那些DTU警告 - 并且已经调整到S2来解决这个问题。但它并不能解决并发问题。 我会采用Analysis Services方法,但如果我没有弄错,这需要某种计划汇总,不是吗? 感谢您的帮助!希望标准层获得专栏商店的支持,因为我不相信高级层将成为一种选择 –