49

Dapper dot net 有一个buffer参数(一个布尔值),但据我所知,它唯一要做的就是在返回结果之前将结果转换为列表。

根据文档

Dapper 的默认行为是执行您的 sql 并在返回时缓冲整个阅读器。这在大多数情况下是理想的,因为它最大限度地减少了数据库中的共享锁并减少了数据库网络时间。

但是,在执行大量查询时,您可能需要最小化内存占用并仅根据需要加载对象。为此,将 buffered: false 传递到 Query 方法中。

我不确定将结果转换为列表如何实现这一点。我错过了什么吗?我唯一的想法是它应该为 to 设置CommandBehaviorExecuteReaderCommandBehavior.SequentialAccess它没有)。

4

3 回答 3

52

但据我所知,它唯一做的就是在返回结果之前将结果转换为列表

你没有错过任何东西。这是关键的区别。除非它不是这样的强制转换:实际返回的对象非常不同。基本上,有两种读取数据的方式:

  • 在流式 API 中,每个元素都是单独产生的;这是非常节省内存的,但是如果您对每个项目进行大量后续处理,则意味着您的连接/命令可能会在很长一段时间内处于“活动状态”
  • 在缓冲 API 中,所有行都在产生任何内容之前被读取

如果您正在读取大量数据(数千到数百万行),那么非缓冲 API 可能更可取。否则会使用大量内存,甚至在第一行可用之前可能会有明显的延迟。但是,在大多数常见场景中,读取的数据量都在合理的范围内,因此在将其交给调用者之前将其推送到列表中是合理的。这意味着命令/阅读器等在返回之前已经完成。

作为旁注,缓冲模式还避免了常见的“连接上已经有一个打开的阅读器”(或任何确切的措辞)。

于 2012-10-02T21:16:16.540 回答
7

在这点上我不得不不同意@chris-marisic...data.ToList()当使用buffered:true时,我在该行 ( ) 处遇到了多个“内存不足”异常。这不是一个“亿万行 X 亿列”查询,只是一个常规的 5-6k 行 SQL 结果,大约有 30 列。

这真的取决于你的配置。例如,您的 SQL 和 IIS 是否在同一台物理机器上运行。以及在 IIS 机器上安装了多少内存,以及页面文件设置是什么等。如果 Web 服务器有 2 GB 或更少 - 考虑为超重报告设置“缓冲:假”。

于 2016-05-19T16:34:44.723 回答
2

在实践中,最好不要使用 buffered: false.

我发现甚至阅读了数百万行,使用缓冲结果比使用无缓冲结果更快,内存效率更高。如果您的表有 500 列并且您正在读取数以百万计或数以亿计的行,则可能存在交叉点。

如果您的结果集小于数十亿个值,则buffered: false出于任何原因都不值得使用。

在实际分析过程中,我感到震惊的是,在标准缓冲模式下,从 Sql Server 读取千兆字节数据的速度更快(快 2-6 倍)和内存效率更高。性能提升甚至考虑了可能的最微小操作,通过索引将对象添加到稀疏数组到不调整大小的数组。使用多 GB 稀疏数组从无缓冲切换到有缓冲,加载时间提高了 2 倍。使用缓冲写入字典时,在插入数百万条记录时加载时间提高了 6 倍(字典使用表的 int PK 作为键,以便尽可能地进行哈希码计算)。

与有关性能的所有事情一样,您必须始终进行分析。但是我可以非常肯定地告诉你,总是从 Dapper 的默认缓冲行为开始。

于 2015-05-27T21:47:19.720 回答