线程不会加快对databse sqlalchemy的调用

时间:2018-04-22 22:23:49

标签: python multithreading sqlalchemy

所以我试图尽可能地简化问题。我知道这看起来像一面文字,但我试着给你一些背景。我创建了一个超过6百万行的简单sqlite数据库。测试表看起来像这样:

class Backlog(Base):
    __tablename__ = "files"
    id = Column(Integer, primary_key=True)
    filename = Column(String)
    date = Column(Date)

我试图看看它是否可以同时进行多线程调用,以便我获得更快的I / O.

阅读文档并检查SO后,我决定使用scoped_session。获取代码如下所示:

from sqlalchemy import *
from sqlalchemy.orm import sessionmaker, scoped_session, Session
import queue
import threading
import time


def get_sql_proc(ThreadSession):
    some_session = ThreadSession()
    sql = text('select * from files')
    call = some_session.execute(sql)
    res = call.fetchall()
    ThreadSession.remove()
    return res


def add_func_to_thread(q, func, kwargs):
    q.put(func(**kwargs))

engine = create_engine('sqlite:///christmas.db', echo=False)
session_factory = sessionmaker(bind=engine)
ThreadSession = scoped_session(session_factory)

q = queue.Queue()
st = time.time()
threads = list()
for i in range(1, 4):
    t = threading.Thread(target=add_func_to_thread, 
                         args=(q, get_sql_proc, {'ThreadSession': ThreadSession}))
    t.daemon = True
    t.start()
    threads.append(t)

for x in threads:
     x.join()

print(time.time()-st)

这将获得大约88秒的运行时间。但是当我一个接一个地调用它们时,我得到的运行时间约为27秒:

engine = create_engine('sqlite:///christmas.db', echo=False)
session = Session(engine)

st = time.time()
for i in range(1, 4):
    w = session.execute('select * from files').fetchall()
print(time.time()-st)

我在MS SQL Server上进行了相同的测试,并得到了类似的结果。我对我做错了什么很困惑,为什么用多线程方法这么慢,任何提示或技巧都会受到赞赏

1 个答案:

答案 0 :(得分:1)

一些背景

Python有Global Interpreter Lock因此在任何给定时间实际上只会发生一次操作。 Python threading模块提供了concurrency, but not parallelism.

作为一个非常简单的类比,你可以想到在你面前有两副牌,你想看看两个牌组中的每张牌。穿线模块呈现自己好像从每个牌组中挑选一张牌并同时读取两张牌,但在幕后它只是将牌组混合在一起并一次看一张牌。

在不知道许多私密细节的情况下,我猜测性能不如预期,因为"线程"调用实际上是串行发生的,在这种情况下,线程的额外开销只会起到性能损害的作用。

解决方案

Python为multiprocessing提供了一种不同的并行方法 模块。它产生(或能够或产生取决于使用)一个新的解释器进程,它并行运行所需的功能。在进程之间共享内存比使用线程更复杂,因此它可能不如将threading.Thread更改为multiprocessing.Process那么简单。