2011-03-12 44 views
6

我正在构建一个线程类来使用Python和MySQLdb运行MySQL查询。我不明白为什么运行这些查询线程比运行它们非线程慢。这是我的代码来展示我在做什么。为什么我在Python中对线程化MySQLdb查询比相同的非线程查询慢?

首先,这里是非线程函数。

def testQueryDo(query_list): 

    db = MySQLdb.connect('localhost', 'user', 'pass', 'db_name') 
    cursor = db.cursor() 

    q_list = query_list 
    for each in q_list: 
     cursor.execute(each) 
     results = cursor.fetchall() 

    db.close() 

这里是我的线程类:

class queryThread(threading.Thread): 

    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 

     self.db = MySQLdb.connect('localhost', 'user', 'pass', 'db_name') 
     self.cursor = self.db.cursor() 

    def run(self): 
     cur_query = self.queue.get() 
     self.cursor.execute(cur_query) 
     results = self.cursor.fetchall() 
     self.db.close() 
     self.queue.task_done() 

而这里的处理程序:

def queryHandler(query_list): 
    queue = Queue.Queue() 

    for query in query_list: 
     queue.put(query) 

    total_queries = len(query_list) 
    for query in range(total_queries): 
     t = queryThread(queue) 
     t.setDaemon(True) 
     t.start() 

    queue.join() 

我不知道为什么这个线程代码的运行速度。有趣的是,如果我使用相同的代码,只做一些简单的事情,比如添加数字,线程代码是显着更快

我明白我一定会错过一些完全明显的东西,但是任何支持都将非常感谢!

回答

2

您正在启动N个线程,每个线程都创建自己的与MySQL的连接,并且您正在使用同步队列将查询传递给线程。每个线程在queue.get()(获取排他锁)上阻塞以获取查询,然后创建到数据库的连接,然后调用task_done(),让下一个线程继续。所以,当线程1工作时,N-1线程什么都不做。这种锁获取/释放的开销,加上连续创建和关闭数据库连接的额外开销会增加。

+0

此外,CPython只允许一次运行一个线程(由于GIL),所以即使... – 2011-03-12 23:29:00

+0

啊,我的印象是,他们同时运行!谢谢samplebias!如果我使用多个进程来分叉每个查询,还是有更好/更有效的方法来处理我缺少的线程,效率会更高吗? – mudda 2011-03-13 00:54:39

+0

真的取决于你的应用程序,但是有些东西会提高你上面的例子的性能:使用一个较小的线程池并向每个线程传递几个查询,而不是每个线程,让每个线程重复使用它的数据库连接进行多个查询。如果您决定使用'fork',则可以尝试使用[multiprocessing](http://docs.python.org/library/multiprocessing.html)模块,以便与子流程进行通信。 – samplebias 2011-03-13 02:49:09