关于大量数据导出到 excel 或 csv 实现方案

2019-08-15 11:40:41 +08:00
 imherer

最近有个需求,需要将 PostgreSQL 里的数据导出到 excel 里(或者 csv ),可能出现的情况有 3 种:

现在问题是如果导出的数据太大的话会 OOM,如何解决呢?

现在想预估一个安全行数,在导出的行数达到安全行数后就保存这个 excel,然后再从数据库读取再追加到这个 excel 里。疑问是再次向这个文件里追加数据的时候这个文件里之前已有的数据会载到内存里来吗?

有做过的前辈分享下经验吗?

语言:go

公司内部项目,所以用户量很少,基本上就几个人使用

7735 次点击
所在节点    程序员
46 条回复
auser
2019-08-15 15:15:12 +08:00
@wayne1027

文件格式本身不限制,但身边环境大家常用的 Numbers.app 不支持打开 65535 行的 csv.

最麻烦的是这个格式在与 Windows 系统交换时经常遇到乱码问题。目前统一使用 xlsx.
imherer
2019-08-15 15:20:07 +08:00
@auser 对,我现在也遇到了,在 Mac 下导出 csv 中文正常,windows 下导出就乱码…… 头疼……
imherer
2019-08-15 15:31:09 +08:00
@maierhuang 嗯,但是好像不支持参数
COPY (SELECT * FROM test LIMIT $1) to '/absolute path/file_name.csv' with csv header
直接报错
auser
2019-08-15 15:31:15 +08:00
@imherer

哈哈,对于文本格式的文件,还有 BOM 这个可能出现的“小坏蛋”呢。

几年前刚接触新团队的时候,现有成员全部用的 Windows 开发。Windows 的 git 有个换行符自动转换功能,可是很多人安装 git for windows 的时候一直下一步或者压根就不知道这个问题,加上 git 图形版客户端与编辑器各用各的,源码文件跟 git diff 没办法看。我还遇到一个项目内的某些源码文件竟然编码不唯一的神奇问题,很诡异,也很好奇怎么会出现这种情况。这个大型 C++项目在 VS 下有时候编译不过去,最后发现也是文件编码问题造成的。

这是纯文本文件固有的问题。

所以有统一的跨平台格式,优先选择它可能会少遇到些绊脚石。
Vegetable
2019-08-15 15:36:40 +08:00
xls 65535,xlsx 大概是一百来万行,所以这两个基本就不考虑了,没等 oom 本身就已经装不了这么多数据了.
只能是 csv.csv 可以 stream 进去,完全不存在 oom 的问题.
gamexg
2019-08-15 15:44:25 +08:00
csv 格式省心, 打开文件一行一行的写,内存不会炸。

没用过 pg@go,查了下也是支持 stream 的: https://github.com/go-pg/pg/issues/82
gamexg
2019-08-15 15:57:47 +08:00
@gamexg #26 确认了,lib/pg 也是默认就是游标方式工作,直接用 go 的 sql 标准库就可以处理大量数据。
mengdodo
2019-08-15 16:00:33 +08:00
pandas 就问你要多大
habicat
2019-08-15 16:12:08 +08:00
pandas+1
lmingzhi08
2019-08-15 16:47:25 +08:00
感觉可以先将数据表 copy to 导出一个 csv 文件,csv 本身是一个文件文件,然后可以按行数切割文件了

http://burnignorance.com/linux-tips-and-tricks/splitting-a-large-csv-files-into-smaller-files-in-ubuntu/

To split large CSV (Comma-Separated Values) file into smaller files in Linux/Ubuntu use the split command and required arguments.

split -d -l 10000 source.csv tempfile.part.

Here “ 10000 ” indicates that each new file contains 10000 records,you change it to any number you want to, the smaller files would have that number of records. The new files are created with numbers suffixed. For example in this case the file names are tempfile.part.00.csv, tempfile.part.01.csv and so on.
changdy
2019-08-15 20:32:44 +08:00
我也在好奇 excel 用什么语言做导出比较合适.
楼上有提到过 阿里巴巴的 开源项目.
但是个人感觉从命名到来看 代码并不美观.并且封装的也不够完整.
想问下 V2EX 的各位道友 用什么语言的那个项目比较合适?

@imherer 友情提示 win offcie 默认是 gbk... 这方面都不如 wps.
abcbuzhiming
2019-08-15 23:34:19 +08:00
@Michaelssss excel 是存在最大行限制的。所以如果打算导出为 excel,无论是 xls 还是 xlsx 都得考虑最大行限制
danmu17
2019-08-16 02:42:17 +08:00
不出意外的话你的需求就是 pandas 典型的应用场景。
loading
2019-08-16 07:03:44 +08:00
先查总条数
然后循环分批读写,每次一万行写一个 csv
然后根据总天数得到你 csv 个数,你可以预设到一个 unix 时间戳建立的文件夹,叫 1.csv 2.csv

最后是打压缩包下载还是 copy 拼起来就看你们了。
windedge
2019-08-16 07:09:01 +08:00
用 petl, 对文本文件(csv), petl 内存占用很低, 写法也很简单:

```
import petl as etl
import psycopg2
connection = psycopg2.connect('dbname=example user=postgres')
table = etl.fromdb(connection, 'SELECT * FROM example')
etl.tocsv(table1, 'example.csv')
```
IamNotShady
2019-08-16 07:48:31 +08:00
写到文件就行了 分批次写
Mithril
2019-08-16 08:01:20 +08:00
写大文件可以 File Mapping,很容易。
但是不建议做成 CSV,这东西不是一个非常标准的规范,总有各种各样的问题。
如果你导出的数据只是内部使用,可以直接导出到 Sqlite 或者 Access 数据库。
这种的 Excel 也能直接用
sonyxperia
2019-08-16 08:28:03 +08:00
直接用 dump 嘛
wqzjk393
2019-08-16 10:09:12 +08:00
先考虑下你是不是真的需要这么多数据这么多字段,保存成 excel csv 以后无论用什么工具打开都会非常慢,保存下来真的能用到么?
maierhuang
2019-08-16 10:28:09 +08:00
@imherer 那直接在外面拼接好了 sql 再执行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/592061

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX