应用程序与数据库的一个连接,还是每次执行时的连接?

问题描述 投票:0回答:2

我正在使用 psycopg2 库连接到我的 postgresql 数据库。 每次我想执行任何查询时,我都会像这样建立一个新连接:

import psycopg2

def run_query(query):
    with psycopg2.connect("dbname=test user=postgres") as connection:
        cursor = connection.cursor()
        cursor.execute(query)
        cursor.close()

但我认为为整个应用程序执行建立一个连接会更快:

import psycopg2

connection = psycopg2.connect("dbname=test user=postgres")


def run_query(query):
    cursor = connection.cursor()
    cursor.execute(query)
    cursor.close()

那么在我的应用程序的所有执行时间内连接数据库的更好方法是什么?

我已经尝试了两种方法并且都有效,但我想知道哪种更好以及为什么。

python postgresql psycopg2
2个回答
4
投票

您应该强烈考虑使用连接池,正如其他答案所建议的那样,这比每次查询时创建一个连接的成本更低,并且可以处理单独一个连接无法处理的工作负载。

创建一个名为 mydb.py 的文件,并包含以下内容:

import psycopg2
import psycopg2.pool
from contextlib import contextmanager

dbpool = psycopg2.pool.ThreadedConnectionPool(host=<<YourHost>>,
                                      port=<<YourPort>>,
                                      dbname=<<YourDB>>,
                                      user=<<YourUser>>,
                                      password=<<YourPassword>>,
                                      )

@contextmanager
def db_cursor():
    conn = dbpool.getconn()
    try:
        with conn.cursor() as cur:
            yield cur
            conn.commit()
    """
    You can have multiple exception types here.
    For example, if you wanted to specifically check for the
    23503 "FOREIGN KEY VIOLATION" error type, you could do:
    except psycopg2.Error as e:
        conn.rollback()
        if e.pgcode = '23503':
            raise KeyError(e.diag.message_primary)
        else
            raise Exception(e.pgcode)
     """
    except:
        conn.rollback()
        raise
    finally:
        dbpool.putconn(conn)

这将允许您像这样运行查询:

import mydb

def myfunction():
    with mydb.db_cursor() as cur:
        cur.execute("""Select * from blahblahblah...""")

1
投票

这两种方式都不好。第一个特别糟糕,因为打开数据库连接的成本相当高。第二个是不好的,因为你最终会得到一个连接(太少)每个进程或线程一个连接(通常太多)。

使用连接池。

© www.soinside.com 2019 - 2024. All rights reserved.