微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python:提高性能 - 在单独的线程中写入数据库

如何解决Python:提高性能 - 在单独的线程中写入数据库

我正在运行一个 python 应用程序,出于各种原因,我不得不将我的程序托管在世界一个地方的服务器上,然后将我的数据库放在另一个地方。

我通过一个简单的脚本进行了测试,从我在邻国的家到数据库服务器,从数据库写入和检索一行的时间约为 0.035 秒(这是一个不错的速度 imo) 0.16 秒,当我在世界另一端的 python 服务器执行相同的操作时。 这是一个问题,因为我试图让我的 python 应用程序尽可能快,所以我想知道是否有一种聪明的方法来做到这一点?

当我同步运行我的代码时,我的程序每次必须写入数据库时​​都在等待,大约每秒 3 次,因此时间加起来。是否可以在单独的线程或其他线程中运行与数据库的连接,以便在尝试将数据发送到数据库时不会停止整个程序?或者可以使用 asyncio 来完成(我没有使用异步代码的经验)?

我真的很难找到解决这个问题的好方法。 提前,非常感谢!

解决方法

是的,您可以创建一个在后台执行写入的线程。在您的情况下,有一个队列似乎是合理的,其中主线程放置要写入的内容,而数据库线程获取和写入它们。队列可以有一个最大深度,以便当有太多东西待处理时,主线程会等待。你也可以做一些不同的事情,比如放弃发生得太快的事情。或者,使用同步的数据库并写入本地副本。您也可能有机会通过一次提交多个来加快写入速度。

这是一个工作线程的草图

import threading
import queue

class SqlWriterThread(threading.Thread):

    def __init__(self,db_connect_info,maxsize=8):
        super().__init__()
        self.db_connect_info = db_connect_info
        self.q = queue.Queue(maxsize)
        # TODO: Can expose q.put directly if you don't need to
        # intercept the call
        # self.put = q.put
        self.start()

    def put(self,statement):
        print(f"DEBUG: Putting\n{statement}")
        self.q.put(statement)

    def run(self):
        db_conn = None
        while True:
            # get all the statements you can,waiting on first
            statements = [self.q.get()]
            try:
                while True:
                    statements.append(self.q.get(),block=False)
            except queue.Empty:
                pass
            try:
                # early exit before connecting if channel is closed.
                if statements[0] is None:
                    return
                if not db_conn:
                    db_conn = do_my_sql_connect()
                try:
                    print("Debug: Executing\n","--------\n".join(f"{id(s)} {s}" for s in statements))
                    # todo: need to detect closed connection,then reconnect and resart loop
                    cursor = db_conn.cursor()
                    for statement in statements:
                        if statement is None:
                            return
                        cursor.execute(*statement)
                finally:
                    cursor.commit()       
            finally:
                for _ in statements:
                    self.q.task_done()

sql_writer = SqlWriterThread(('user','host','credentials'))
sql_writer.put(('execute some stuff',))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?