使用Postgresq的Python多线程处理

2024-04-28 16:02:54 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

downloader.get_data(con)
con.close()

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

问题是这个过程非常慢,因为在get_data()内,类一次只下载一个记录。我已经开始将此更改为包含线程:

^{pr2}$

我所做的只是再次创建一个downloader实例。然后创建3个线程,每个线程运行get_data,方法是向它传递一个指定要下载哪些记录的参数。在

我没有创建psycopg2连接并将其传递给get_data,而是在get_data中创建了连接,这样每个线程都有自己的连接。在

我的问题是,这是否足够和正确,以确保所有线程将“发挥良好”与数据库同时?每个线程仍然使用相同的用户名/密码访问数据库。我通过向每个线程传递一个records_to_download参数来确保每个线程都将更新不同的记录。在

我听说过连接池,但是对于这样一个单用户、多线程的设置来说,这是不是有点过分了?(我从未使用过连接池,而且我的数据库知识非常基础,…因此,如果不需要这样做,那么我会避免它)。在

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


Tags: 数据实例方法服务器数据库应用程序data参数
1条回答
网友
1楼 · 发布于 2024-04-28 16:02:54

is that sufficient and correct to ensure all the threads will 'play nice' with the database simultaneously?

实际上,这是实现并行的最直接的方法。在

(注意,PostgreSQL实际上支持通过单个连接的并行性,但据我所知,它只在in the C driver可用。 还有executemany和用一个INSERT语句插入多行的技巧(参见this question)。在

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

为此,您可能希望通过在用于批量更新的每个连接中发出SET synchronous_commit TO off来稍微放松持久性。(参见synchronous_committhis question)。在

或者,您可以将更新分组到大型事务中,将磁盘问题的持久性延迟到事务提交。在

I have heard about connection pooling but is that overkill for a one user, multi-thread setup such as this?

连接池主要用于降低建立和断开连接的成本。在某些设置中,它还可以减少数据库需要维护的连接数。在

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

在这样一个重复的任务中,第二步和第四步通常通过某种连接池进行优化。在

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

这里每个服务器进程都保持自己的数据库连接,以避免每次有请求时都建立新的数据库连接。所以,如果有200个PHP进程在运行,那么就有200个数据库连接。这将从数据库服务器获取RAM来维护连接。可以改用连接池来实现类似的性能,而不需要维护200个连接。在

在您的场景中,我认为没有必要使用连接池。另外,拥有自己的连接允许您使用synchronous_commitwork_mem等进一步优化它们,这在使用连接池时是不可取的,因为如果将调整后的连接留在池中,可能会以不受控制的方式影响其他池用户的耐用性和性能。在

Lastly, is there a limit to how many threads I can use for this kind of setup before being forced to use a more robust approach such as connection pooling? Or is connection pooling required right from the get go?

多线程不是灵丹妙药。您只需要尽可能多的线程和连接就可以克服驱动程序与数据库通信的串行性所带来的瓶颈(实际上,如果您要使用异步流水线版本的C驱动程序,那么您可能根本不需要线程),并达到数据库服务器配置和硬件所要求的性能。在这个问题上投入比需要更多的线程只会分散系统的大脑,使其工作更慢(参见Reasons for Performance Reduction Past the "Knee")。在

通过测试和测量,为您的用例提供最佳的线程和连接数。在

性能是您的极限,在问题上投入太多线程,性能就会受到影响。在

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

相关问题 更多 >