Python 如何从列表中多线程读取词典并将其输入数据库

Python 如何从列表中多线程读取词典并将其输入数据库,python,multithreading,Python,Multithreading,我正在尝试对以下代码进行多线程处理,但似乎无法使其正常工作 下面的代码(我删除了其中的大部分代码只是为了说明目的)目前运行平稳,但运行缓慢(对于3600条tweet的列表,大约需要5分钟) 因此,我正在寻找一个选项来完成这个多线程的任务。但是,我还没有找到一种方法来: 多线程的抽取过程 每100、500或1000条推文打印一个计数器 经历这些还没有让我理解到这一点:每个线程都有一个类的概念,我现在需要在类中定制什么,实现一个队列,这些都是我现在需要掌握的;我只是半开始 有没有人能提供一些提

我正在尝试对以下代码进行多线程处理,但似乎无法使其正常工作

下面的代码(我删除了其中的大部分代码只是为了说明目的)目前运行平稳,但运行缓慢(对于3600条tweet的列表,大约需要5分钟)

因此,我正在寻找一个选项来完成这个多线程的任务。但是,我还没有找到一种方法来:

  • 多线程的抽取过程
  • 每100、500或1000条推文打印一个计数器
经历这些还没有让我理解到这一点:每个线程都有一个类的概念,我现在需要在类中定制什么,实现一个队列,这些都是我现在需要掌握的;我只是半开始

  • 有没有人能提供一些提示,告诉我如何利用多个线程合并上面的脚本
  • 我应该使用多少线程?Python当前在运行脚本时使用约1%的CPU和约10%的RAM(my)
  • 我如何处理递增计数器(使用Lock()?),并在命中计数器%100时打印
编辑:按要求编辑:以下是探查器结果(使用dataset.upsert)中的要点:

下面是第二次尝试使用“dataset.insert”而不是“dataset.upsert”:

1386332 function calls (1382960 primitive calls) in 137.255 seconds

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  2955  122.646    0.042  122.646    0.042 :0             (_connect)
最后(绝对不是最不重要的),这里是运行原始psycopg2代码的时间

63694 function calls (63680 primitive calls) in 2.203 seconds
最后,不要使用dataset来提高性能(尽管编写psycopg2代码花了我10分钟,这对于dataset.upsert来说是>>10秒)

  • 现在,关于原来的问题。通过多线程处理,我是否能够进一步减少每个文件的~2秒?怎么做

可以找到完整的代码

我不知道您是否能够提高性能。但至于我认为你会想要并发的.futures.Executor.map。ProcessPoolExecutor而不是ThreadPoolExecutor应该是您想要的,尽管我不是专家


如果您想显示进度,请查看concurrent.futures.as\u在同一模块中完成的内容。

可以改进的几点:

在单个事务上运行整个批处理。使用事务意味着数据库不需要在每次写入时实际提交(将数据写入磁盘),而是可以在内存中缓冲未提交的数据。这通常会导致更高效的资源使用

在tweet_id上添加唯一索引。如果没有唯一索引,您可能会强制数据库对每个upsert进行顺序扫描,从而导致批量upsert按O(n**2)进行缩放


拆分插入和更新,尽可能使用.insert\u many()而不是.upsert()。在进行批量升级之前,您需要进行飞行前查询,以找出数据库和您的tweet列表中存在的tweet_id列表。使用.insert\u many()插入数据库中不存在的项,并使用.update()插入已存在的项。

看起来您没有CPU限制,因此多线程可能只会降低速度。如果像我所怀疑的那样,您受到I/O的限制,那么通过购买更快的硬盘,您将获得更好的性能提升,这听起来很悲哀。但是,在走这条路之前,请检查其他进程,例如RDBMS。Python当前正在从我的SSD运行,数据库(PostgreSQL)正在从USB 3.0连接的外部驱动器运行。我正在读取的文件位于7200rpm硬盘上(尽管我认为这不会影响性能,因为列表已经在内存中了?)。你会推荐不同的设置吗?我无法想象它是硬件?在我们能够编写有效的并发代码之前,我们需要了解瓶颈是什么。例如,我不明白为什么处理3600条推文需要5分钟。您知道哪些特定线路占用的时间最多吗?可以帮你回答这个问题。分析是个好主意。您的示例让人相信,
dataset
的性能非常差。如果是这样的话,线程就没用了。您可以尝试执行
.insert
而不是
.upsert
,但您确实希望与标准sql insert(尤其是具有多个值的sql insert)进行比较。添加探查器结果后,似乎“\u connect”已运行了约90%的时间。现在尝试使用备用调用(.insert,直接使用psycopg2)生成备用结果。
1386332 function calls (1382960 primitive calls) in 137.255 seconds

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  2955  122.646    0.042  122.646    0.042 :0             (_connect)
63694 function calls (63680 primitive calls) in 2.203 seconds