postgresql - PQsetSingleRowMode 低性能

标签 postgresql fetch libpq

我目前正在使用 libpq 为 PostgreSQL 实现一个适配器,我想知道通过 PQsetSingleRowMode ( https://www.postgresql.org/docs/9.6/static/libpq-single-row-mode.html ) 设置的单行模式是否存在已知的性能问题?

我的印象是,在这种模式下,libpq 将使用比游标和显式 FETCH 所能实现的更智能/更高效的缓冲。

但是,当运行 10 倍的简单查询时(“从 mytable 中选择 id”,返回 5000 条记录)。使用 PostgreSQL 9.6.3(在客户端和服务器端),我观察到以下性能模式:

  • PQexecParams(同时完成):78 毫秒
  • PQsetSingleRowMode:3047 毫秒(大部分花费在 PQgetResult 中)
  • PQexecParams + FETCH 1:3313 毫秒(大部分花在 PQgetResult 上)
  • PQexecParams + FETCH 10:219 毫秒

所以单行模式似乎比创建游标和逐行获取更有效……这是正确的行为吗?还是有其他一些选项来控制单行模式?

(在我的使用案例中,就某些查询的内存使用而言,一次获取所有内容会有风险,因此实际上是在单行模式或一次获取几条记录之间进行选择)

附加问题:有没有办法轻松中途中止获取单行模式? 当使用 cursor+fetch 时,这是微不足道的,但对于单行模式,看来您要么需要获取所有结果,要么使用 PQcancel)

附录: 再次使用分析器运行,发现 PQgetResult 对 malloc 和 free 的调用是瓶颈(分别占 CPU 时间的 60% 和 30%),这两个函数都来自 MSVCR120 AFAICT(这是在 Win 10 下,服务器是本地主机) .我正在使用“官方”PostgreSQL zip 中的 libpq.dll。有趣的是,在基准测试之前运行其他查询“有时”可以使问题消失。看起来 PQgetResult 正在攻击 malloc/free 的弱点。

最佳答案

这是令人惊讶的。

虽然您肯定可以预期重复调用 PQgetResult 会产生一定的开销,但它不应该像您观察到的那么多。

我用 localhost 上的数据库运行了一个返回 500 万行的查询测试,单行模式需要略多于两倍的 CPU 用户时间(总执行时间主要由数据库服务器决定)处理时间)。

5000 行 3 秒听起来很可疑,可能还有其他原因。

尝试分析可执行文件以查看时间花在了哪里。

关于postgresql - PQsetSingleRowMode 低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44722256/

相关文章:

sql - 在 90 天的窗口中,我有多少不同的活跃用户?

postgresql - COPY FROM 是否写入事务日志?

ruby-on-rails - 带 % 通配符的 Rails SQL 查询在 SQLite 中有效但在 PostgreSQL 中无效?

javascript - 使用 jQuery 从外部 JSON 站点获取数据,Singleton 类

Hibernate:代理实现细节(Lazy Fetching)

postgresql - libpq:如何在 PGconn 连接失败后获取错误代码

ruby-on-rails - Rails 会无限期地使用单个 "database session"吗?

fetch - Z80内存刷新寄存器

postgresql - PQconnectdb 在连接时设置 search_path (schema)

c - 类型转换。我如何处理 C 中 libpq 中的 PostgreSQL OID 值?