在postgres中估算SQL请求的结果大小

时间:2019-11-04 15:13:17

标签: postgresql

我设置了一个postgres + nodejs系统,该系统根据用户输入执行查询。由于服务器资源受到限制,我想防止查询结果过大而无法放入RAM或超出我设置的限制。

查询生成可能会有些复杂,具体取决于输入,而我查询的表如下所示:

id | id_something_related | timestamp | varchar32_A | varchar32_B | jsonb_data  (with different names of course)

由于表包含jsonb数据(非固定大小),所以我不能使用简单的LIMIT来限制最大行数。

我目前的解决方案是执行第二个查询,该查询封装了第一个查询并返回其大小:

SELECT COALESCE(sum(pg_column_size( _data.* )), 0) as total_size_byte FROM ( ...REAL QUERY HERE.... ) as _data

第一个查询为我提供了一个大小,可以用来决定是否要执行该查询。 与此相对的是,它两次运行查询,这代表了服务器上的大量开销。

我会很高兴:

  • 一种查询语法,可以防止以字节为单位的太大结果
  • 可以估计另一个查询的结果大小的查询(但是以某种精度为代价,运行速度更快)
  • 一个查询系统,使我能够获取结果大小来决定是否要下载它(例如postgres持有的临时缓冲区)。请注意,数据库位于同一台服务器上,所以我也不想postgres填充RAM)
  • 用于设置最大结果大小的postgres设置
  • 一个nodejs选项,当查询结果达到给定大小时,它将停止下载查询结果。 (我正在使用https://www.npmjs.com/package/pg
  • 任何其他解决方案(请注意,失去太大的结果不是问题)

1 个答案:

答案 0 :(得分:1)

这个问题的简单而经典的解决方案是使用游标并一次或批量获取结果。然后,只要超出限制,您就可以停止获取。

任何其他解决方案都将不得不依赖估计,因此不精确。您可以检查EXPLAIN的查询结果,如this blog post末尾所示。由于不仅要关注行数,而且要关注每行的大小,所以您还希望检索平均结果行的width(以字节为单位)。

但是我认为使用游标是国王的方式。