1

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

经过一些实验,我意识到在一个表中存储一亿条记录并不能很好地工作:索引步骤很快就会慢到爬行。对于这个问题,我可以想出两个解决方案:

  1. 将数据划分为多个表
  2. 将数据划分为多个数据库

我采用了第二种解决方案(它产生了几个大文件而不是一个大文件)。我的分区方法是看主键的前两个字符:每个分区大约有200万条记录,大约有50个分区。

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

不幸的是,插入速度在一段时间后仍然下降到无法忍受的水平(大约 1000 万条总处理记录)。我能做些什么来解决这个问题?有没有更好的方法来做我正在做的事情?

4

2 回答 2

5
  • 将所有插入命令包装到单个事务中。
  • 使用准备好的语句。
  • 只有在插入所有数据后才创建索引(即,不声明主键)。
于 2013-07-24T06:13:06.637 回答
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 数据库是这个问题的最佳解决方案吗?

于 2013-07-24T06:26:10.247 回答