包含来自SQL Azure的具有大型NVARCHAR值的列的查询很慢

时间:2016-08-23 01:43:52

标签: sql-server entity-framework azure-sql-database

我在Azure数据库中有一个表,它已经开始慢慢地对查询做出响应。 查询如下所示:

SELECT [Id] --nvarchar(128), PrimaryKey
      ,[Name] --nvarchar(max)
      ,[Description] --nvarchar(max)
      ,[Modified]  --datetime2(7)
      ,[LastModifiedBy] --nvarchar(max)
      ,[Opened]  --datetime2(7)
      ,[Editor] --nvarchar(max)
      ,[Json] --nvarchar(max)   <--THIS IS GIVING ME PROBLEMS
      ,[IsActive] --bit
  FROM [dbo].[TableName]

具体来说,当我在查询中包含[Json]列时,SQL查询性能从不到一秒钟变为几分钟。当包含[Json]列时,即使仅请求单个记录也可能需要几分钟。此列包含长json格式的字符串(~500000个字符)。当包含此列时,性能仅会中断 - 包含较小字符串的其他NVARCHAR(max)列不是问题。

我通过使用实体框架linq-to-entities查询的MVC5应用程序的性能问题发现了这个问题:

var model=await db.TableName.FirstOrDefaultAsync(s => s.Id == id);

生成了一个类似上面的SQL查询。在本地开发机器上运行没有问题的单个案例的Edit方法在服务器上加载需要几分钟。然后,我查看了直接数据库查询以查看问题所在并找到了较长的查询时间。

这种性能问题在不同的查询方法中并不一致。

我的周转时间为3分钟,并带有以下查询:

SELECT Json FROM [dbo].[TableName] WHERE [Id]=<id>

周转时间与返回的字符串长度成指数比例。例如,此查询大约需要10秒钟:

SELECT SUBSTRING(Json,1,50000) FROM [dbo].[TableName] WHERE [Id]=<id>

服务器上的查询(如下所示)不到一秒钟。:

DECLARE @variable nvarchar(max);
SELECT @variable=Json FROM [dbo].[TableName] where Id='<id>';
SELECT LENGTH(@variable);

但实际上如下所示检索数据会让我回到几分钟:

DECLARE @variable nvarchar(max);
SELECT @variable=Json FROM [dbo].[TableName] where Id='<id>';
SELECT @variable;

我的最终目标是弄清楚如何让Entity Framework的linq-to-entities查询以合理的速度执行,这样我就可以使用C#中的数据了,我认为我不能强制EF生成这样的动态查询。

在使用存储大字符串的其他表之前,我从未遇到过这种困难。是否有错误地设置错误的设置,或者在这种情况下是否有建立EF linq-to-sql语句的最佳实践?

为了进行比较,使用同一数据库的副本在SQL Server的本地实例上运行查询时没有性能问题;所有查询都在不到一秒的时间内返回。

-UPDATE -

我一直在监控,这个问题已经消失,没有任何代码更改。所有查询响应时间都回到不到一秒。但是,Azure也没有关于服务中断的通知。事实上,在整个问题期间,数据库是完全可访问的,唯一的问题是涉及返回大字符串值的字段的慢查询。

缺点是我无法再重现这个问题。

对于Azure上存在此问题的其他人(似乎不规则),此行为的诊断症状为:

  1. 没有Azure-SQL Server中断
  2. 不返回大字符串值的查询的健康响应时间
  3. Azure-SQL Server对任何查询的正常资源使用情况,即使它们返回大字符串值
  4. 在依赖的应用程序中,连接应用程序抛出两种类型的错误:a)连接超时错误,以及b)关闭的连接错误。没有任何上下文信息可以区分何时抛出任何类型的错误。
  5. 涉及长字符串的查询的响应时间是指向返回字符串的长度的指数。例如,10个字符是瞬时的,50000需要10秒,500000需要几分钟等。但是,响应时间不一致。
  6. 完全在不需要返回长字符串值的服务器上执行的字符串处理(即使在非常长的字符串上)也需要正常的时间。
  7. 如果某人有实际答案,我会保留此问题,但似乎解决方案是等待Azure解决他们正在修改的有关其请求处理的任何内容。似乎该问题与从Azure DB传输数据而不是服务器上的处理有关。 我的最高建议是,如果问题的特征是上述症状,请不要拆开在开发盒上完美运行的代码。

2 个答案:

答案 0 :(得分:1)

真的太糟糕了,你无法重现这个错误,因为我已经考虑过你的问题,而这一切都来自你的陈述&#34;当我在[Json]列中包含查询时,SQL查询性能从不到一秒钟到几分钟。&#34;你也给了我一些线索:

服务器上的查询(如下所示)不到一秒钟。:

DECLARE @variable nvarchar(max);
SELECT @variable=Json FROM [dbo].[TableName] where Id='<id>';
SELECT LENGTH(@variable);

检索数据时,问题是等待类型:ASYNC_NETWORK_IO。基本上将数据发送出sql server并进入应用程序等待就是问题所在。

我会问应用程序在哪里运行。应用程序是否位于与数据库相同的数据中心中,或者是否在数据中心外部运行。越接近应用程序数据,您就越少看到此等待类型。

我要问的另一个问题是运行应用程序的硬件,它是否有足够的内存来接收所有数据,然后以有用的方式处理它。有时,网络等待实际上是应用程序端的供电硬件问题。

我还有一些额外的想法要分享:如果您要处理非常大的JSON对象,您是否考虑过使用DocumentDB来存储它们,而不是Azure SQL数据库?它针对这种工作负载进行了优化,现在您可以编写T-SQL来查询存储在DocumentDB中的JSON文件。

关于:

  

在依赖应用程序中,连接应用程序抛出两种类型的错误:a)连接超时错误,以及b)关闭的连接错误。没有任何上下文信息可以区分何时抛出任何类型的错误。

在任何打到数据库的应用程序中,您都需要某种重试策略。在处理Azure SQL数据库时,这是至关重要的,因为在任何给定时间您都有三个数据库副本,并且您可能需要在一天中间进行故障转移。如果您有重试策略,最终用户将永远不会知道存在问题,因为辅助副本可在一秒钟内完成。

我希望这有帮助!

答案 1 :(得分:0)

这听起来像是返回nvarchar(max)的一般问题所以也许联系Azure支持团队会更好:

由于此问题可以重现并且代码中没有一些修复,因此我不知道Azure支持团队以外的其他人如何提供帮助。