Python 为什么psycopg2对我这么慢?

Python 为什么psycopg2对我这么慢?,python,postgresql,profiling,psycopg2,cprofile,Python,Postgresql,Profiling,Psycopg2,Cprofile,我有一个使用psycopg2与postgres合作的程序。 但是在DB中插入太长时间 下面是使用cProfile进行分析的结果 ncalls tottime percall cumtime percall filename:lineno(function) 475 0.022 0.000 855.605 1.801 /home/user/my_project/db.py:197(insert_event) 475 0.012 0.000 293.347

我有一个使用psycopg2与postgres合作的程序。 但是在DB中插入太长时间

下面是使用cProfile进行分析的结果

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
475    0.022    0.000  855.605    1.801 /home/user/my_project/db.py:197(insert_event)
475    0.012    0.000  293.347    0.618 /home/user/my_project/db.py:123(insert_meta)
475    0.026    0.000  276.814    0.583 /home/user/my_project/db.py:102(insert_image)
2375 0.022 0.000 598.542 0.252 /usr/local/lib/python2.7/dist-packages/psycopg2/extras.py:286(execute)
1425  251.676    0.177  251.676    0.177 {method 'commit' of 'psycopg2._psycopg.connection' objects}
475    0.005    0.000   33.028    0.070 /home/user/my_project/db.py:83(is_event)
结论:

Insert full information about one event - 1.8 sec
Insert a picture (average) - 0.583 sec
Insert meta data about an event (average) - 0.618 sec
Confirmation of transaction (average) - 0.177 sec
Check availability of a record in DB - 0.070 sec
下面是使用psycopg2的代码

class PostgresDb(object):
    def __init__(self, host, port, name, user, password, connect=True):
        self.host = host
        self.port = port
        self.name = name
        self.user = user
        self.password = password
        self.connection = None
        self.cursor = None
        if connect:
            self.connect()

    def __str__(self):
        return ' '.join(map(str, [self.host,
                                  self.port,
                                  self.name,
                                  self.user]))

    def connect(self):
        try:
            self.connection = psycopg2.connect(host=self.host,
                                               port=self.port,
                                               user=self.user,
                                               password=self.password,
                                               database=self.name)
            self.cursor = self.connection.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)

        except psycopg2.DatabaseError as e:
            print e
            return e.pgerror

    def execute(self, query,  commit=True, repeat=True):
        if self.connection is None:
            self.connect()
        try:
            self.cursor.execute(query)
            if commit:
                self.connection.commit()
        except psycopg2.Error as e:
            print e
            self.connection = None
            return repeat and self.execute(query, commit=commit, repeat=False)
        else:
            return True
我做错了什么


也许您知道为什么需要这么长时间。

根据您的分析结果,您似乎正在提交数千个事务,并且每个事务都会产生相关的开销。对此进行了更深入的讨论

如果您的需求不一定规定这样的粒度事务边界,那么您可以选择将多个插入批处理到单个事务中,然后对该批执行一次提交。对于你在这里发布的内容,这可能等同于这样愚蠢的近似:

db = PostgresDb(...your connection stuff here...)
#
# Other stuff happens, including determining your INSERT queries
#
for query in my_insert_queries[:-1]:
  db.execute(query, commit=False)
db.execute(my_insert_queries[-1], commit=True)

我相信有一百万种方法可以将洋葱切成小方块,这取决于您的代码的其余部分是什么样的-建议的核心是减少提交的事务的数量。

Psycopg2对我来说也很慢。Python中的低CPU使用率、Postgres中的低CPU使用率和查询花费了很长时间。我不知道这是我的数据库连接还是什么,但这是不能容忍的

试试这个:当你想做一堆查询时,确保它们以分号结尾,然后把它们加在一个字符串中。不要单独运行它们。在末尾将那个巨大的字符串作为查询运行。如果您需要在事务进行到一半时从数据库中选择内容并在Python脚本中使用结果,那么这将不起作用,但无论如何,这可能是一种罕见的情况。这大大加快了我的交易速度

看。使用复制、批处理、同步提交=关闭。。。有很多不同的选择。