如何使用 Pandas 将巨大的 CSV 转换为 SQLite?

How to transform a huge CSV into SQLite using Pandas?

我有一个很大的 table(大约 60 GB)的存档 CSV 文件。我想将它转换成一个 SQLite 文件。

我现在做的事情如下:

import pandas
import sqlite3
cnx = sqlite3.connect('db.sqlite')
df = pandas.read_csv('db.gz', compression='gzip')
df.to_sql('table_name', cnx)

它适用于较小的文件,但对于大文件我有内存问题。问题是 pandas 将整个 table 读入内存 (RAM),然后将其保存到 SQLite 文件中。

这个问题有没有优雅的解决方案?

由于其大小,pandas 会出现问题。您不能使用 csv 模块而只能遍历文件的任何原因。

基本思路(未经测试):

import gzip
import csv
import sqlite3

with gzip.open('db.gz') as f, sqlite3.connect('db.sqlite') as cnx:
    reader = csv.reader(f)
    c = cnx.cursor()
    c.executemany('insert into table_name values (?,?,...)', reader)

我还没有用那种大小的 CSV 做过任何工作,但听起来这种事情 Odo 可能会很快解决。

我粗略地检查了文档,他们似乎已经 written something 解决了 larger-than-memory CSV 解析到 SQL 数据库的主题,该数据库专门调用 SQLite3 作为目的地。

这是他们发布的用于解析 33 GB 文本文件的示例。

In [1]: dshape = discover(resource('all.csv'))

In [2]: %time t = odo('all.no.header.csv', 'sqlite:///db.db::nyc',
   ...:               dshape=dshape)
CPU times: user 3.09 s, sys: 819 ms, total: 3.91 s
Wall time: 57min 31s

[更新于 2017 年 6 月 15 日]

似乎 csv2sqlite.py 可能是使用 SQLite 的方法。毫无疑问,Chuck-by-Chuck 对于大文件(> 1GB)来说太慢了。当我用 csv2sqlite.py 测试一个 6.5GB 的 nyc311calls.csv 时,只用了大约 24 分钟就创建了一个数据类型猜测的 SQLite 数据库文件。 24 分钟与 MySQL 和 "LOAD DATA INFILE" 的花费时间相似。即使您可能需要更改某些列的数据类型,这也不错。在我看来,使用 csv2sqlite.py 是目前从 csv 文件创建 SQLite 数据库文件最省时的方法。

1) 从here 下载一个csv2sqlite.py 并将其放在包含csv 文件的目录中。

2) 通过使用 Windows Prompt,转到包含 csv2sqlite.py 和要导入的 csv 文件(例如 nyc311calls.csv)的目录。

3) 运行 python csv2sqlite.py nyc311calls.csv database_name.db 的代码并等待。注意:python PATH 应包含在您的 Windows Environment Variables.


这是一个有点老的任务,但似乎没有人给出明确的答案。 希望我的回答对您有所帮助。对于 Sqlite,我建议您查看 this site,它为您提供了想法和您应该做什么,逐块加载。我测试了几种方法,但到目前为止,这是我认为最可靠的方法。

基本流程是这样的: 1)将大table的一小部分导入到pandas。 2)处理并将它们加载到SQLite。 3) 继续这个过程。

我上传了我所做的更详细的过程here (Jupyter file) if you are interested in. You can find the NYC311call data here

我的一些评论。

1) 如果您的数据包含空字符串,Odo 包将无法正常工作。我希望他们能改善这些问题。也就是说,如果您的数据非常干净且组织良好,Odo 包可能是您的选择。

2) 上述方法是一项非常耗时的工作。特别是,一个 ~6GB 的 table 需要超过 24 小时。因为 pandas 很慢。

3) 如果你不坚持使用 SQLite,我会说 MySQL 和 "LOAD DATA INFILE" 对你来说是个不错的选择。您可以从互联网搜索中找到如何使用它。只要我测试过,这是非常可靠和有效的方式。如果你真的需要使用 sqlite,你可以转换到 sqlite。特别是,如果数据有很多空字符串和 datetime 列,需要转换为 datetime 类型,我肯定会选择 MySQL。