我用Django adaptors上传一个简单的CSV。当我导入100或200个联系人时,它似乎工作得很好。但是当我试图上传一个165kb的文件,有5000个联系人时,它始终没有完成。我让它继续努力,当我一小时后回来时,它还在努力。在
这怎么了?使用Django adaptors导入一个165kb文件不可能需要一个小时以上。代码有问题吗?
def process(self):
self.date_start_processing = timezone.now()
try:
# Try and import CSV
ContactCSVModel.import_data(data=self.filepath, extra_fields=[
{'value': self.group_id, 'position': 5},
{'value': self.uploaded_by.id, 'position': 6}])
self._mark_processed(self.num_records)
except Exception as e:
self._mark_failed(unicode(e))
csv模型
^{pr2}$
我会首先检查csv中没有数据错误。例如,如果一个列有错误的转义字符或不正确的数据类型-也许数据库不能接受某些列上的空值。在
当它挂起时,你能手动检查数据库是否正在填充吗?是通过命令行MySQL提示符还是workbench?如果是,则自动提交被打开,您应该能够看到它挂在哪一行上,然后在CSV中检查该记录。在
但是,如果auto commit被关闭(我不知道Django在默认情况下做了什么,或者您的数据库是如何配置的),那么可能是事务缓冲区溢出了。应该有一种方法可以分阶段手动刷新/提交事务来解决这个问题。在
把你的大任务分成小块。在
第1步-读取CSV文件
两者兼而有之ContactCSVModel.import_from_文件名()和ContactCSVModel.import_from_文件()返回csv行。禁用与django模型的交互以跳过与数据库的交互。这将大大加快任务的速度并打印导入的数据。这肯定有用!在
CSV模型
你的代码
^{pr2}$第2步-启用django模型交互,但禁用检查数据库中的现有项。
禁用它,因为启用此功能将根据您的自然键规范(我已经阅读了源代码)查询CSV中每一行的DB,以检查现有项。也许你知道CSV中的所有行都是唯一的联系人。在
如果您的问题是整个导入过程中的数据库查询速度慢,这将有所帮助,但如果导入消耗了太多内存,则不会有真正的帮助。在
第3步-导入大小相等的CSV块
使用CSVModel并启用与联系人模型的交互,但为ContactCSVModel.import_数据(). 我把它设为500。根据你的需要改变它。下面的代码示例(link)是为了让您明白这一点。您需要对其进行一些更改,以便将其放入现有代码中。如果这是内存消耗问题的话。在
第4步-针对大内存消耗和慢操作
由于django适配器在导入期间将所有联系人模型实例保存在内存中,并且由于多个单次提交而不是大容量插入操作,django适配器的操作速度较慢,因此它不太适合较大的文件。在
你有点依赖django适配器。如果依赖这个django包,就不能切换到批量插入。使用top或htop在linux下使用task manager检查内存消耗。如果进程消耗太多,并且操作系统开始交换,那么切换到另一个django插件,可以选择使用更高效的内存消耗和大容量插入,其中有很多用于csv导入。在
另一个提示是使用csv模块进行读取,并使用django模型知识与数据库交互。这对你来说并不是一个真正的挑战-只要试着把你的大局中的一些孤立的任务放在一起,如果它们正在工作的话-祝你好运。在
首先尝试将iterable传递给
import_data
函数:第二件事是使用
^{pr2}$import_from_filename
:如果这没用,试着弄清楚它挂在哪里。您可以通过减小csv文件的大小来手动执行此操作,或者您可以在
csv.reader
上放置一个模拟,或者您可以模拟CsvImporter.process_line,而不是处理行,而是打印出来看看它在哪里停止。如果你需要嘲笑的帮助,请告诉我。在另外,这个issue也可能是相关的。在
相关问题 更多 >
编程相关推荐