使用 JdbcTemplate 从数据库中读取大数据并通过 api 公开?

Posted

技术标签:

【中文标题】使用 JdbcTemplate 从数据库中读取大数据并通过 api 公开?【英文标题】:Read large data from database using JdbcTemplate and expose via api? 【发布时间】:2020-06-29 22:26:14 【问题描述】:

我需要从 postgres 数据库中读取一个大型数据集,该数据库需要通过 rest api 端点进行访问。使用数据的客户端需要将数据转换为 csv 格式(以后可能需要支持 json 和 xml)。

在服务器端,我们使用 Spring Boot v2.1.6.RELEASE 和 spring-jdbc v5.1.8.RELEASE。 我尝试使用分页并遍历所有页面并将结果存储到列表中并返回列表,但由于数据集不适合内存而导致OutOfMemory 错误。

流式传输大型数据集似乎是处理内存限制的好方法。 有什么方法可以只返回所有数据库实体的 Stream 并让其余 api 将相同的内容返回给客户端?客户端将如何反序列化此流?

除此之外还有其他选择吗?

【问题讨论】:

这可以通过 webflux 和响应式数据库来实现。您是否使用 webflux 进行反应流,您的数据库是什么? 数据库是postgres,使用spring-jdbc v5.1.8的NamedParameterJdbcTemplate查询数据库。我查看了 r2dbc-postgresql 的反应式数据库,但它还不是 GA。 【参考方案1】:

如果您的数据太大以至于无法放入内存(我认为是千兆字节或更多),那么它可能太大而无法合理地作为单个 HTTP 响应提供。您将保持连接打开很长时间。如果您在中途遇到问题,客户需要从头开始,可能在几分钟前。

更用户友好的 API 会引入分页。您的调用者可以指定页面大小和要获取的页面索引作为其请求的一部分

例如

 /my-api/some-collection?size=100&page=50

这表示从第 5000 个 (5000 - 5100) 开始获取 100 个项目

也许您可以根据一次能够加载到内存中的内容对页面大小设置一些合理的限制。

【讨论】:

我最终使用分页来调用其余客户端并使用StreamingResponseBody 写入数据。感谢您提出这个建议。 @mosranna 当然,很乐意提供帮助

以上是关于使用 JdbcTemplate 从数据库中读取大数据并通过 api 公开?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 spring JdbcTemplate 读取_未提交?

使用 jdbcTemplate 进行分页

从 POST 方法中使用 JDBCTemplate 存储对象数组 - Spring Boot

JDBCTemplate RowMapper 读取 postgres 表中的 jsonb 列

数据库操作之Spring JDBCTemplate(postgresql)

Spring 从入门到精通系列 11—— Spring 中的 JdbcTemplate