我使用bulk_create将1 mio记录插入到新表中.这需要80秒. Django只使用一个cpu核心(大约25%的cpu,但没有核心达到100%)我相信有改进潜力.
这是代码
class Stock(models.Model): code = models.CharFIEld(max_length=6,unique=True) name = models.CharFIEld(max_length=8)class Watchers(models.Model): date = models.DateFIEld(db_index=True) stock = models.ForeignKey(Stock,unique_for_date="date") num = models.PositiveIntegerFIEld(default=0)batch = []for input in inputs: watcher = Watcher(date=input['date'],stock=get_stock(),num=input['num']) batch.append(watcher)Watcher.objects.bulk_create(batch)
我尝试了几件事:
>使用正确的batch_size.对我来说最好的价值大约是4000.它需要80-90秒.
>使用ThreadPool().它慢得多,大约120-140秒
>删除DateFIEld上的索引.比1慢一点.
我正在使用MysqL 5.6社区版.存储引擎是MyISAM.这是配置.
[MysqLd]server-ID = 1default-storage-engine = MyISAMport = 3306socket = /tmp/MysqL.sockdatadir = "{MysqLDATAPATH}"skip-external-lockingexplicit_defaults_for_timestamp = TRUE# MyISAM #key-buffer-size = 32Mmax_allowed_packet = 16M# CACHES AND liMITS #tmp-table-size = 32Mmax-heap-table-size = 32Mquery-cache-type = 0query-cache-size = 0max-connections = 500thread-cache-size = 50open-files-limit = 65535table-deFinition-cache = 1024table-open-cache = 2048# LOGGINGlog-bin = MysqL-binbinlog_format = mixed
当我导入另一个表(类似的结构,相同的索引,但有9列),它需要15分钟.时间增加不是线性的.
bulk_create有什么问题吗?
更新1
虽然我接受了答案,但我想我应该理解这个谜.所以我做了一些测试,发现Django的模型创建是减速的根本原因.当我有800000条记录时,调用800000次创建模型将非常耗时.
ORM框架执行许多我们没有看到的内部工作,例如完整性检查.在我的例子中,大量记录将被导入到空数据库表中,因此不需要检查.
现在我使用cursor.executemany(),它将800000个4列记录的插入时间从54秒缩短到16秒.并将800000个13列记录的插入时间从13分钟缩短到46秒.
根据我的实验,你会为每3000-5000条记录调用executemany.我在一次通话中尝试了800k记录,这非常慢.
最佳答案虽然bulk_create对于在处理HTML表单时保存少量记录很有用,但它并不适合保存数千条记录.正如您已经发现的那样,它很慢,因为它需要大量内存并向数据库发送一个非常大的查询. Fortunatley LOAD DATA IN FILE来救援.The LOAD DATA INfile statement reads rows from a text file into a
table at a very high speed. LOAD DATA INfile is the complement of
SELECT … INTO OUTfile.
我们可以生成类似于使用csv writer生成的文件,以下示例来自文档.
import csv with open('some.csv','wb') as f: writer = csv.writer(f) writer.writerows(someiterable)
最后,正如您已经发现的那样,有时可以使用LOAD DATA …的LOCAL选项.
LOCAL works only if your server and your clIEnt both have been
configured to permit it
使用此选项时,无需手动将文件传输到服务器.您可以在客户端生成CSV文件,local选项将使MysqL客户端自动将文件传输到服务器.
总结If LOCAL is not specifIEd,the file must be located on the server host
and is read directly by the server.
以上是内存溢出为你收集整理的mysql – 大量记录的bulk_create的最佳实践全部内容,希望文章能够帮你解决mysql – 大量记录的bulk_create的最佳实践所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)