我正在使用 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()
那么在我的应用程序的所有执行时间内连接数据库的更好方法是什么?
我已经尝试了两种方法并且都有效,但我想知道哪种更好以及为什么。
您应该强烈考虑使用连接池,正如其他答案所建议的那样,这比每次查询时创建一个连接的成本更低,并且可以处理单独一个连接无法处理的工作负载。
创建一个名为 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...""")
这两种方式都不好。第一个特别糟糕,因为打开数据库连接的成本相当高。第二个是不好的,因为你最终会得到一个连接(太少)每个进程或线程一个连接(通常太多)。
使用连接池。