Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 处理数百万条记录并保存回数据库的有效方法是什么?_Django_Multithreading_Postgresql - Fatal编程技术网

Django 处理数百万条记录并保存回数据库的有效方法是什么?

Django 处理数百万条记录并保存回数据库的有效方法是什么?,django,multithreading,postgresql,Django,Multithreading,Postgresql,我在Python2.7中使用Django。我有一张有数百万行的excel表格。我必须操作行数据并保存回数据库postgresql。我想有效地做这件事。 以下是我想到的方法: 一,。将队列中的所有行数据排队(最好是RabbitMQ),并一次获取100个条目。并将执行和 将它保存在数据库中 二,。考虑在后台使用线程,每个线程将管理100行,并将结果保存回数据库。我不是 确定在此场景中将打开多少个数据库连接 你能给我一个有效的方法来实现这一点吗。这将非常有用。您可以在Django请求处理程序中创建其他

我在Python2.7中使用Django。我有一张有数百万行的excel表格。我必须操作行数据并保存回数据库postgresql。我想有效地做这件事。 以下是我想到的方法:

一,。将队列中的所有行数据排队(最好是RabbitMQ),并一次获取100个条目。并将执行和 将它保存在数据库中

二,。考虑在后台使用线程,每个线程将管理100行,并将结果保存回数据库。我不是 确定在此场景中将打开多少个数据库连接


你能给我一个有效的方法来实现这一点吗。这将非常有用。

您可以在Django请求处理程序中创建其他线程,每个线程都有自己的数据库连接。但问题是,使用多个TheAD时,数据库插入性能会提高多少

例如,如果您的表具有唯一的约束,这可能会降低并发写入的速度。然后,您可能会发现真正的瓶颈是磁盘带宽,并且您无法通过添加连接来扩展太多

因此,在进行过多优化之前,您可能需要编写一些快速而肮脏的测试代码,以尝试对相关表/数据库进行多线程并发写入

至于如何在线程之间有效地分配数据,这取决于输入格式

如果您正在处理Microsoft格式的文件,如.xls,则需要使用库来解析该文件。。我成功地使用了xlrd。但这会导致所有电子表格数据同时存储在内存中。。你不能一次读一行。但假设您可以处理内存使用情况,那么线程就变得简单了:一旦您将所有数据读入内存,启动多个writer线程,告诉每个writer线程它负责写入的行号范围。然后,主请求线程可以加入writer线程,当它们全部完成时,它可以向用户返回响应。但是,请记住,如果您的请求耗时过长,浏览器将超时。这是一个不同的问题,为此,我建议看看前几天我写的关于如何使用StreamingHttpResponse的另一个答案:

现在,如果您的输入格式类似于.csv文件,您可以一次读取一条记录,那么一种可能的处理方法是使用python队列类创建内存队列。启动writer线程,让它们在队列中侦听要写入数据库的记录,然后让主线程从.csv文件中一次读取一条记录,并将这些记录放入队列中

这些建议都是为了在Django请求中正确处理您的数据。但如果您不想这样做,可以通过各种方式卸载处理。正如您所提到的,您当然可以使用rabbitmq,并让多个侦听器进程进行编写。这会起作用,但我不确定它是否会达到最佳效率。您需要编写所有记录,因此将它们拆分,将它们发送到另一个进程,然后将它们从那里发送到另一个进程,这并不一定有帮助。。。除非这些其他进程正在其他机器上运行

如果您正在读取一个已经写入磁盘的文件的数据,并且该文件是一种很容易再次分割的文件格式,例如CSV,那么一种简单且非常经典的方法就是将文件大小除以您拥有的写入线程数。告诉每个编写器要处理的文件的起始偏移量和结束偏移量。每个写入程序(从偏移量0开始的写入程序除外)都可以向前搜索,直到找到记录分隔符(例如)。\r\n。然后,它开始一次读取和处理一条输入记录,直到读取到等于或超过其结束偏移量的位置

如果您正在从请求中读取文件,并且希望在请求处理程序之外对其进行处理,您可能会发现,将其作为一个大文件写入磁盘,然后按照上面所述进行后续处理更为有效


总之,请尝试找到处理数据的方法,以使读写次数最少。如果可以,就地处理数据,如果不需要,不要移动数据。如果其他进程在同一台机器上,请避免写入它们,因为手头的进程是磁盘密集型的。如果您确实希望能够轻松扩展到更多机器,那么请尝试rabbitmq。我用它,它很好,很快。但这会增加开销,所以除非你能从分手中得到一些真正的好处,否则这可能会让你放慢速度。不过,它确实使进程间的通信超级容易。

难道你不能将excel保存为.csv并使用COPY命令吗?我必须对每行中的数据进行操作,然后在操作后将其保存到
数据库在这种情况下,实现取消和暂停的最佳方式是什么?比如,如果用户取消了它,那么其余的线程或进程应该被取消编辑实际上取决于你如何实现你的网页,如果它是一个没有JavaScript的简单表单帖子,那么用户可以在上传过程中点击浏览器上的“停止”按钮,但一旦请求被处理,如果您想停止它,您就必须向发送一个单独的请求以终止线程。。您可以在会话中存储有关的信息。。。