当前位置:  开发笔记 > 编程语言 > 正文

使用Postgresql进行Python多线程处理

如何解决《使用Postgresql进行Python多线程处理》经验,为你挑选了1个好方法。

我有一个非常基本的应用程序,通过套接字连接从服务器一次下载一个记录的数据,并将每个记录写入postgresql数据库.这仅供我使用.

downloader = DataDownloader.Downloader()
con = psycopg2.connect(datebase='db', user='username', password='pswrd')

downloader.get_data(con)
con.close()

在上面的代码中,我将psycopg2连接传递给一个类的实例,然后执行所有下载和数据库更新.

问题是这个过程非常慢,因为在get_data()课堂上一次只下载一个记录.我已经开始改变它以包含线程:

downloader = DataDownloader.Downloader()

records_to_download = 'abc'
thread1 = threading.Thread(target=downloader.get_data, args=(records_to_download))
thread1.start()

records_to_download = 'xyz'
thread2 = threading.Thread(target=downloader.get_data, args=(records_to_download))
thread2.start()

records_to_download = 'ghj'
thread3 = threading.Thread(target=downloader.get_data, args=(records_to_download))
thread3.start()

我所做的就是再次创建一个downloader实例.然后创建3个线程,每个线程运行get_data一个参数,指定要下载的记录.

而不是创建一个psycopg2连接并将其传递给get_data我而不是在其中创建连接,get_data以便每个线程将拥有它自己的连接.

我的问题是,是否足以确保所有线程同时与数据库"玩得很好"?每个线程仍使用相同的用户名/密码来访问数据库.我确保每个线程都会通过传递一个records_to_download参数来更新不同的记录.

我听说过连接池,但对于一个用户来说,这样的多线程设置是否有点过分?(我从未使用连接池,我的数据库知识非常基础,...所以如果没有必要,那么我会避免它).

最后,在被迫使用更强大的方法(如连接池)之前,我可以使用多少线程进行此类设置?或者从一开始就需要连接池?



1> ArtemGr..:

是否足够和正确,以确保所有线程同时与数据库"玩得很好"?

实际上,这是实现并行性的最直接的方法.

(请注意,PostgreSQL实际上通过单个连接支持并行性,但据我所知,它只能在C驱动程序中随时可用.还有executemany用单个INSERT语句插入多行的技巧(参见这个问题)).

既然您通过多个连接实现了高效的并行性,那么您应该检查服务器端的瓶颈.特别是,以ACID所需的超级持久方式将事务提交到磁盘可能会使更新变慢,因为它们正在等待操作系统和存储设备报告有效负载的成功到达.

为此,您可能希望通过发布SET synchronous_commit TO off用于批量更新的每个连接来放宽持久性.(参见synchronous_commit和这个问题).

或者,您可以将更新分组到大型事务中,从而延迟磁盘的持久性问题,直到事务提交为止.

我听说过连接池,但对于一个用户来说,这样的多线程设置是否有点过分?

连接池主要用于减轻建立和拆除连接的成本.在某些设置中,它还可以减少数据库需要维护的连接数.

考虑以下用例:1)用户访问服务器页面; 2)服务器建立数据库连接; 3)服务器通过查询数据库来检查用户是否存在; 4)服务器断开连接; 5)服务器将页面发送给用户.

在这样的重复任务中,通常利用某种连接池来优化第二和第四步骤.

另一个用例:1)用户访问服务器页面; 2)服务器进程建立并缓存数据库连接; 3)服务器通过查询数据库来检查用户是否存在; 4)服务器将页面发送给用户.

这里每个服务器进程都保持自己的数据库连接,以便每次有请求时都不建立新的数据库连接.因此,如果您有200个PHP进程在运行,则有200个数据库连接.这需要从数据库服务器获取RAM以维护连接.可以使用连接池来实现类似的性能,而无需维护200个连接.

在您的方案中,我认为不需要连接池.还拥有自己的连接,可以让你调整它们进一步与synchronous_commit,work_mem等,使用连接池时,因为留在池中微调的连接时,您可能会影响以不受控制的方式耐久性及其他泳池用户的性能这是不可取的.

最后,在被迫使用更强大的方法(如连接池)之前,我可以使用多少线程进行此类设置?或者从一开始就需要连接池?

多线程不是一颗银弹.您只需要尽可能多的线程和连接来抵消驱动程序与数据库通信的串行性质所带来的瓶颈(实际上,如果您使用C驱动程序的异步流水线版本,那么您可能不需要线程处理所有)并达到数据库服务器配置和硬件强加的性能.在问题上投入比所需更多的线程只会使系统分散,使其工作更慢(参见"膝盖"之后性能降低的原因).

测试和测量为您的用例提供最佳线程数和连接数.

性能是你的极限,在问题上抛出太多线程,性能会受到影响.

至于连接池,您只需要在特定用例中使用它.

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有