2009-11-18 81 views
1

我有GUI将与postgres数据库交互,使用psycopg2。我在多处理进程中有db连接,并通过多处理队列发送SQL,并通过另一个队列接收。python多处理db访问非常慢

问题是速度非常慢。一个简单的select *从一个小表(30行)可以是十分之一秒,或可以超过一秒钟。

有没有人有任何线索,为什么它如此缓慢?

新的信息:它的工作原理在WinXP,完全相同的代码罚款,所以间歇延迟仅发生在我的Linux机器(Ubuntu的9.10)

更多信息:已经灭掉它看起来的选择不是问题。

这是db类的主要部分。

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  

而在GUI我有这样的:

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 

回答

0

尝试找出什么是花时间 - 是它的多或数据库?例如,尝试直接从python交互式shell调用数据库 - ipython shell有'time'和'timeit'命令来测量这样的事情。或者,将DataBase.execute存根以返回罐头值,并查看它所产生的差异。

那么gobject.timeout_add呢?那是干什么的?延迟可能在那里,而不是数据库或多处理代码。

+0

是的,我已经尝试过。只需在一个进程中运行一个100选项,从shell使用“time python db_test.py”时需要大约0.3秒(包括python启动时间) 当我今晚返回时,我将给出一些值(不包括linux在工作中) timeout_add在请求发送到数据库后开始轮询队列,它是GUI主循环的一部分,允许用户继续与应用程序进行交互。 – Rob 2009-11-18 18:34:17

0

您是否尝试过为每个进程打开新的数据库连接?在我看来,你只是增加开销,试图在不同的进程中重用它们。

此外,我不确定(你的示例是小的推断),但它看起来像你打开每个查询的新数据库连接...你是否在每个查询后关闭与self.conn.close()的连接?你应该有一个持久的联系。

+0

我为每个进程打开一个新的连接,但在应用程序运行的整个过程中保持打开状态。这允许不同的对象具有它们自己的单独事务。 我会为每个查询创建一个新的游标。 – Rob 2009-11-18 18:31:19

+0

尝试在分析器下运行您的代码。 – liori 2009-11-18 22:23:40

0

这似乎是问题或者具体到Ubuntu 9.10

所有工作正常,在Ubuntu 9.04和Win32,甚至在Win32托管在Ubuntu 9.10虚拟机上的错误。

感谢您的所有建议。