Python多进程数据库访问非常慢

1 投票
3 回答
1243 浏览
提问于 2025-04-15 16:07

我有一个图形用户界面(GUI),它会和一个Postgres数据库进行交互,使用的是psycopg2这个库。我在一个多进程的环境中建立了数据库连接,通过一个多进程队列发送SQL语句,然后通过另一个队列接收结果。

问题是速度非常慢。简单地从一个小表(30行数据)中选择所有数据,有时候只需要0.1秒,但有时候却要超过1秒。

有没有人知道为什么会这么慢呢?

新信息:在Windows XP上运行得很好,代码完全一样,所以这种间歇性的延迟只发生在我的Linux机器上(Ubuntu 9.10)。

更多信息:我已经把选择操作的部分简化了,看来这不是问题所在。

这是数据库类的主要部分。

class DataBase(multiprocessing.Process):

    def __init__(self, conn_data, in_queue, out_queue):
        multiprocessing.Process.__init__(self)
        self.in_queue = in_queue
        self.out_queue = out_queue
        self.conn_data = conn_data
        self.all_ok = True

    def run(self):  
        proc_name = self.name
        self.conn = self.get_connection(self.conn_data)
        print("Running ", self.name)
        while True:
            next_job = self.in_queue.get()
            print("Next Job: ",next_job)
            if next_job is None:
                # Stop Process
                break
            SQL = next_job[0]
            callback = next_job[1]
            result = self.execute(SQL)
            self.out_queue.put((result, callback))
        print("Closing connection ", self.name)
        self.conn.close()
        return      

在图形用户界面中,我有这个:

def recieve_data(self):
    "Revived data on the queue.  Data is a tuple of the actual data and a calback name."
    if self.recieve_queue.empty() == False:
        data = self.recieve_queue.get()
        callback_name = data[1]
        try:
            callback = getattr(self, callback_name)
            callback(data[0])
        except AttributeError as e:
            util.error_ui(err = e)
        self.check_data_timeout = None
        return False # Stop checking.
    return True  # Have the main loop keep checking for data.

def request_data(self, SQL, callback):
    self.send_queue.put((SQL, callback))
    self.check_data_timeout = gobject.timeout_add(50, self.recieve_data) # Poll the database recieved_queue

3 个回答

0

试着找出到底是什么在耗费时间——是多进程处理还是数据库的问题?比如,你可以直接在Python的交互式命令行中调用数据库。这里有个工具叫ipython,里面有'time'和'timeit'命令,可以用来测量这些操作的时间。或者,你可以把DataBase.execute这个函数暂时改成返回固定的值,看看这样会有什么不同。

那gobject.timeout_add呢?它在干什么?有可能延迟的原因是在这里,而不是数据库或多进程的代码里。

0

你有没有试过为每个进程打开一个新的数据库连接?我觉得你在不同的进程中重复使用连接,反而增加了负担。

另外,我不太确定(因为你的例子太小了,没法判断),但看起来你每次查询都在打开新的数据库连接……你在每次查询后有用self.conn.close()关闭连接吗?其实应该保持一个长久的连接。

0

看起来这是一个只出现在Ubuntu 9.10上的问题或者bug。

在Ubuntu 9.04和win32上都运行得很好,甚至在Ubuntu 9.10的虚拟机上运行win32也没问题。

感谢大家的建议。

撰写回答