将超过一亿行插入SQLite数据库的最佳方法是什么?

时间:2013-07-24 06:07:33

标签: python database sqlite

我有大量CSV格式的数据。我需要能够基于单个文本字段(主键)索引此数据,因此我正在考虑将其输入数据库。我对之前项目的sqlite很熟悉,所以我决定使用那个引擎。

经过一些实验,我意识到在一个表中存储一亿条记录将无法正常工作:索引步骤很快就会慢慢爬行。我可以想出两个解决这个问题的方法:

  1. 将数据分区为多个表
  2. 将数据分区为多个数据库
  3. 我选择了第二个解决方案(它产生了几个大文件而不是一个大文件)。我的分区方法是查看主键的前两个字符:每个分区有大约200万条记录,大约有50个分区。

    我在Python中使用sqlite3模块执行此操作。在整个过程中,我保持50个打开的数据库连接并打开游标。对于每一行,我查看主键的前两个字符,通过字典查找获取正确的光标,并执行单个插入语句(通过在光标上调用execute)。

    不幸的是,插入速度在一段时间后仍然会降低到难以忍受的水平(大约1000万个处理过的记录)。我该怎么做才能解决这个问题?有没有更好的方法来做我正在做的事情?

2 个答案:

答案 0 :(得分:5)

  • 将所有插入命令包装到单个事务中。
  • 使用准备好的陈述。
  • 仅在插入所有数据后创建索引(即,不要声明主键)。

答案 1 :(得分:1)

我认为你遇到的问题是,一旦处理不能只使用内存缓冲区,你的硬盘磁头就会在50个位置之间随机跳跃,这很慢。

您可以尝试的只是一次处理一个子集:

seen = {}   # Key prefixes already processed
while True:
    k0 = None  # Current prefix
    for L in all_the_data:
        k = L[0][:2]
        if k not in seen:
            if k0 is None:
                k0 = k
            if k0 == k:
                store_into_database(L)
    if k0 is None:
        break
    seen.append(k0)

这将n+1传递数据(其中n是前缀的数量),但只能访问两个磁盘位置(一个用于读取,一个用于写入)。如果你将物理设备分开,它应该会更好。

PS:您真的确定SQL数据库是解决此问题的最佳解决方案吗?