如何使用Pandas将一个巨大的CSV文件转换成SQLite数据库?

5

我有一个巨大的表格(约60GB),以归档的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将整个表格读入内存(RAM),然后保存到SQLite文件中。

是否有一个优雅的解决方案来解决这个问题呢?


1
read_csv 函数接受一个 chunksize 参数,它会返回指定行数的数据块,这样你就可以迭代地读取 N 行并写入到 sql 中。详见文档:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html#pandas.read_csv - EdChum
你必须使用Python和Pandas吗?为什么不在SQLite的命令行中使用.import呢?参考链接 - cfort
3个回答

7
我没有处理过那么大的 CSV 文件,但听起来像是 Odo 可以快速解决的问题。
我对文档进行了粗略检查,看起来他们已经 编写了一些内容 ,讨论了将大于内存的 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

5
由于其大小,使用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)

2
[更新于06-15-2017]
看起来使用csv2sqlite.py可能是使用SQLite的最佳选择。对于大文件(> 1GB),Chuck-by-Chuck太慢了。当我测试了一个6.5GB的nyc311calls.csv文件时,使用csv2sqlite.py只需约24分钟就可以创建一个带有数据类型猜测的SQLite数据库文件。即使您需要更改某些列的数据类型,24分钟也类似于MySQL使用“LOAD DATA INFILE”的时间。在我看来,使用csv2sqlite.py是从csv文件创建SQLite数据库文件的最有效方法。
1)从此处下载csv2sqlite.py并将其放在包含csv文件的目录中。
2)使用Windows Prompt进入包含csv2sqlite.py和要导入的csv文件(例如nyc311calls.csv)的目录。
3)运行python csv2sqlite.py nyc311calls.csv database_name.db的代码并等待。注意:Python PATH应包含在您的Windows环境变量中。
这是一个有点旧的问题,但似乎没有人给出清晰的答案。我希望我的回答能帮助您。对于Sqlite,我建议您查看此网站,它会给您一个想法和您应该做什么,即逐块加载。我测试了几种方法,但到目前为止,在我看来,这是最可靠的方法。
基本程序如下: 1)将大表的一小部分导入pandas。 2)处理并将它们加载到SQLite中。 3)继续保持此过程。
如果您有兴趣,可以在这里(Jupyter文件)找到我更详细的操作过程。您可以在此处找到NYC311call数据。
我的一些评论。
1)如果您的数据包含空字符串,则Odo包无法完全工作。我希望他们能改善这些问题。即使您的数据非常干净和组织良好,Odo包也可能是一个选项。

2) 上述方法非常耗时。特别是对于一个约6GB的表格,需要超过24小时时间。这是因为pandas运行速度较慢。

3) 如果你不坚持使用SQLite,我建议你尝试使用MySQL和“LOAD DATA INFILE”功能。你可以在网上搜索学习如何使用它。根据我的测试,这是一种更加可靠和高效的方式。如果数据中有很多空字符串和日期时间列,这些都需要转换成日期时间类型,那么我肯定会选择MySQL。之后如果你真的需要使用SQLite,可以将数据转换成SQLite格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接