下单快发货慢:一个 JOIN SQL 引起 SqlClient 读取数据慢的奇特问题

  • 时间:
  • 浏览:1
  • 来源:大发快三_快三客户端下载_大发快三客户端下载

更新:一种问题报告 是 System.Data.SqlClient 的有三个 多 bug 引起的,详见 坑暗花明:又遇 .NET Core 中 System.Data.SqlClient 查询缓慢的问题报告

最近遇到有三个 多 非常奇特的问题报告 ,在有三个 多 ASP.NET Core 项目中从 SQL Server 30008 R2 中查询获取 3000 条记录竟然耗时 10 多秒,将会是查询一种慢,那到全部一定会有哪些奇特的问题报告 。

说它非常奇特是将会耗时主要位于在 SqlDataReader 读取数据时

2019-04-04 21:31:58.546 [Information] Executed DbCommand ("2,656"ms)
...
2019-04-04 21:32:10.690 [Debug] A data reader was disposed.

进一步测试发现

查询获取 1 条数据库记录,耗时在 2300ms 左右  
查询获取 10 条数据库记录,耗时在 1.6s-2s 之间
查询获取 3000 条数据库记录,耗时在 12s-22s 之间

就让就让刚始于 怀疑是 EF Core 的问题报告 ,通过在 EF Core 源码中打点,定位到耗时位于在 _dataReader.ReadAsync 处

while (await _dataReader.ReadAsync(cancellationToken))
{
    _buffer.Enqueue(_valueBufferFactory.Create(_dbDataReader));
}

_dataReader.ReadAsync 实际调用的是 System.Data.SqlClient 中的 SqlDataReader.ReadAsync 最好的办法。

一次 ReadAsync 读取一行记录,通过在 SqlClient 的源代码中打点记录时间戳发现,在 3000 次一行一行读取中,其含有有几个读取会出先延迟,比如某一次 13 秒延迟,3000 次读取中出先了 5 次读取延迟 —— 2s + 3s + 3s + 2s + 3s = 13s 。

经过在 System.Data.SqlClient 源代码中无数次打点记录时间戳最终定位到延迟位于在  SNIPacket.ReadFromStreamAsync()  最好的办法中  stream.ReadAsync()  时

Console.WriteLine($"Entering stream.ReadAsync() at {DateTime.Now}");
stream.ReadAsync(_data, 0, _capacity, CancellationToken.None).ContinueWith(t =>
{
    Console.WriteLine($"stream.ReadAsync().ContinueWith at {DateTime.Now}");
    //...
}

stream 对应的是 NetworkStream ,延迟位于在网络传输过程中,与 SqlClient 没关系。

TCP 抓包发现 SQL Server 服务器发送的数据到达就延迟了。

于是必须将怀疑对象锁定在 SQL Server 数据库层面。

对应的 SQL 查询话语涉及 4 张表,FROM 一张表(表A), JOIN 三张表(LEFT JOIN 表B,LEFT JOIN 表C ,INNER JOIN 表D),表A有30000多万条记录,表C有30000多万条记录,查询时按表A的主键排序,表A的聚集索引建在时间字段上,没人建在主键上。

SELECT ...
FROM TableA
LEFT JOIN TableB ON [TableA].[Id] = [TableB].[EntryID]
LEFT JOIN TableC ON [TableA].[Id] = [TableC].[EntryID]
INNER JOIN TableD  ON [TableA].[BlogID] = [TableD].[BlogID]
WHERE ([TableA].[Id] >= @__startId_0)

并全部一定会所有查询都出先一种问题报告 ,当 @__startId_0 小于一定值一定会出先。

就让尝试将  LEFT JOIN TableC 改为 INNER JOIN TableC ,问题报告 竟然消失了,但进一步测试发现当  @__startId_0  再小到一定值问题报告 又会出先。

既然问题报告 与 JOIN TableC 有关,那干脆不进行 JOIN ,单独查询 TableC ,因此将在 C# 代码中将查询的结果合并进行,另有三个 多 改进了,查询获取 3000 条记录只需 3000 多毫秒。

一种奇特的问题报告 就另有三个 多 用有三个 多 简单粗暴有效的最好的办法临时出理 了。

对于一种问题报告 的根本意味着着,怀疑与 TableA 没人把聚集索引建在 Id 字段上有关,但目前没人修改聚集索引进行验证,就让再找将会验证。

猜你喜欢

2018腾讯游戏创意大赛各奖项惊喜出炉 创意产品颁奖典礼于深圳举行

2018-08-1311:11   江苏热线      你要评论() 字号:T|T8月11日,由腾讯游戏学院联合WeGame、极光计划,一块儿启动的全球游戏行业赛事——2018

2019-12-15

Calvina新闻,Calvina赛程赛果,Calvina数据统计,Calvina阵容,Calvina球员名单

首页新闻视频直播数据APP懂球号广告相互相互合作CalvinaCalvina成立:国家:城市:主场:容纳:人电话:邮箱:地址:赛程<前10场比赛|后10场比赛>01

2019-12-15

JavaScript之引用类型

Object类型是JavaScript中使用最多的有一种类型。真是Object的实例不具备几次功能,但对于在应用tcp连接中存储和传输数据而言,它真是是非常理想的确定。创建Ob

2019-12-15

phpMyFAQ 开源问答系统|phpMyFAQ 开源问答系统 v3.0.0 beta3下载

下载首页最近更新下载排行软件分类源码报导模板下载网站资源论坛Asp源码.net源码PHP源码其它源码书籍教程服务器类网络软件应用软件系统工具图形图像多媒体类安全相关发布软件/源

2019-12-15

史上最囧挑战第六季第26关怎么过

更新时间:2018-08-1714:39:05来源:斗蟹游戏编辑:五个核桃 【斗蟹攻略】史上最囧挑战第六季在最近正式上线了,这次的玩法和后后类似,也是属于恶趣味风格,具体

2019-12-15