我目前正在使用 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/