Jon*_*han 44 django optimization orm bulkinsert
我打算使用django的ORM将从约750个文件(每个~250MB)中取出的十亿条记录上传到数据库.目前每个文件需要大约20分钟才能处理,我想知道是否有任何方法可以加速这个过程.
我采取了以下措施:
我还能做些什么来加快速度?以下是我的一些想法:
欢迎任何关于这些项目或任何其他想法的指针:)
Gar*_*ary 34
Django 1.4 bulk_create()在QuerySet对象上提供了一个方法,参见:
Yan*_*Cao 17
这不是特定于Django ORM,但最近我不得不将超过2000个文件中的大约6千万行8列数据批量插入到sqlite3数据库中.我了解到以下三件事将插入时间从48小时减少到大约1小时:
增加数据库的缓存大小设置以使用更多RAM(默认值总是非常小,我使用3GB); 在sqlite中,这是由PRAGMA cache_size = n_of_pages完成的;
在RAM而不是磁盘中进行日志记录(如果系统出现故障,这确实会引起轻微问题,但考虑到磁盘上已有源数据,我认为可以忽略不计); 在sqlite中,这是由PRAGMA journal_mode = MEMORY完成的
最后也许是最重要的一个:插入时不要构建索引.这也意味着不要声明可能导致DB构建索引的UNIQUE或其他约束.完成插入后才构建索引.
如前所述,您还应该使用cursor.executemany()(或只是快捷方式conn.executemany()).要使用它,请执行:
cursor.executemany('INSERT INTO mytable (field1, field2, field3) VALUES (?, ?, ?)', iterable_data)
Run Code Online (Sandbox Code Playgroud)
iterable_data可以是列表或类似的东西,甚至是打开的文件阅读器.
我在Django 1.10/Postgresql 9.4/Pandas 0.19.0上运行了一些测试,得到了以下时间:
DataFrame.to_sql()但不获取ID:774msdf.to_sql()但不获取ID:574ms.bulk_create(Model(**df.to_records()))以to_csv缓冲和StringIO(COPY),并没有得到编号:118mscur.copy_from()和插入3000行并to_csv通过简单获取ID COPY(可能不是线程安全,除非SELECT WHERE ID > [max ID before insert]在表上保持锁定以防止同时插入?):201msdef bulk_to_sql(df, columns, model_cls):
""" Inserting 3000 takes 774ms avg """
engine = ExcelImportProcessor._get_sqlalchemy_engine()
df[columns].to_sql(model_cls._meta.db_table, con=engine, if_exists='append', index=False)
def bulk_via_csv(df, columns, model_cls):
""" Inserting 3000 takes 118ms avg """
engine = ExcelImportProcessor._get_sqlalchemy_engine()
connection = engine.raw_connection()
cursor = connection.cursor()
output = StringIO()
df[columns].to_csv(output, sep='\t', header=False, index=False)
output.seek(0)
contents = output.getvalue()
cur = connection.cursor()
cur.copy_from(output, model_cls._meta.db_table, null="", columns=columns)
connection.commit()
cur.close()
Run Code Online (Sandbox Code Playgroud)
性能统计数据全部在已经包含在OS X(i7 SSD 16GB)上运行的3,000行的表上获得,平均使用10次运行COPY.
我通过分配导入批处理ID并按主键排序来获取插入的主键,尽管我不是100%确定主键始终按照命令的行序列分配timeit- 无论如何都会欣赏意见.
http://djangosnippets.org/snippets/446/上还有一个批量插入代码段.
这给出了一个插入命令多个值对(INSERT INTO x(val1,val2)VALUES(1,2),(3,4)--etc等).这应该会大大提高性能.
它似乎也有大量记录,这总是一个加号.
| 归档时间: |
|
| 查看次数: |
33568 次 |
| 最近记录: |