我正在尝试使用Python脚本解析维基百科档案。(是的,我知道。)当然:
问题出现在尝试将数百万行插入SQLite数据库(每个维基百科文章一个)。我用于测试的简单版本表如下:
在这个初始阶段,我只有ID和文本字段。当我通过以下方式开始添加行时:
它一开始表现良好。但是在大约800万行左右,它开始急剧减速,降低一个数量级或更多。
当然需要一些细节。我正在使用带有插入语句之前创建的单个游标的
正在读取的源XML和正在写入的数据库位于两个独立的磁盘上,我还尝试在内存中创建数据库,但无论如何我都看到了减速。我还尝试了
- 维基百科XML文件:45.95 GB
- 可用内存:16 GB
问题出现在尝试将数百万行插入SQLite数据库(每个维基百科文章一个)。我用于测试的简单版本表如下:
CREATE TABLE articles(
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL UNIQUE ON CONFLICT IGNORE);
在这个初始阶段,我只有ID和文本字段。当我通过以下方式开始添加行时:
INSERT OR IGNORE INTO articles(title) VALUES(?1);
它一开始表现良好。但是在大约800万行左右,它开始急剧减速,降低一个数量级或更多。
当然需要一些细节。我正在使用带有插入语句之前创建的单个游标的
cur.executemany()
。每次调用此函数都有约10万行的批处理。在所有100万多行都被插入之前,我不会调用db.commit()。根据我所读到的,只要有INSERT
语句,executemany()
就不应该提交事务,直到db.commit()。正在读取的源XML和正在写入的数据库位于两个独立的磁盘上,我还尝试在内存中创建数据库,但无论如何我都看到了减速。我还尝试了
isolation_level=None
选项,在开头和结尾添加了BEGIN TRANSACTION
和COMMIT TRANSACTION
调用(因此整个解析序列是一个事务),但仍然没有帮助。
有一些本网站上的其他问题表明索引是问题所在。我没有在表上创建任何索引。我尝试删除UNIQUE
约束,只限制于id INTEGER PRIMARY KEY
和title TEXT NOT NULL
,但也没有效果。
在SQLite中处理大型数据集的这些类型插入的最佳方法是什么?当然,这个简单的查询只是众多查询中的第一个;还有其他更复杂的查询,涉及外键(此表中的文章ID)以及嵌入的select语句的插入语句(在插入期间从文章表中选择ID)。这些问题必然会出现,但随着行数的增加,性能问题会更加严重-当文章表少于1500万行时,其他表可能会有超过10亿行。因此,这些性能问题变得更加令人担忧。