是我,是你
环境:
Pycharm
Python 3.9.16
安装包:
pip install DBUtils==3.0.3
pip install PyMySQL==1.0.3
回顾上篇
python对PowerPoint(PPT)操作,自动生成PPT文档
九月de云,公众号:九月de云python对PowerPoint(PPT)的增、删、改和插入表格及图片操作,自动生成PPT文档
开始本篇
PooledDB是DBUtils中的一个模块,可以很方便轻松地创建数据库连接池。它可以管理多个数据库连接,并且可以重复使用已经建立的连接,从而减少建立连接的开销。
以下一个简单的例子:
需要查询id为1的数据
# -*- coding: utf-8 -*-
import pymysql
from dbutils.pooled_db import PooledDB
pool = PooledDB(
creator=pymysql,
maxconnections=3,
mincached=2,
maxcached=3,
maxshared=3,
reset=True,
blocking=True,
maxusage=0,
ping=1,
host='localhost',
user='root',
'111111', =
'test', =
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
# 从连接池中获取一个连接
conn = pool.connection()
cur = conn.cursor()
# 执行SQL查询
sql = 'SELECT * FROM users_msg WHERE id=%s'
(1,))
result = cur.fetchone()
result)
# 关闭并将连接归还到连接池
cur.close()
conn.close()
# 关闭连接池
pool.close()
结果:
查询结果为:{'id': 1, 'name': 'Nancy Hc', 'age': 26, 'score': 84.76}
其中参数的介绍:
creator: 数据库连接对象的构造函数
maxconnections: 连接池的最大连接数。如果设置为0或None,则没有限制
mincached: 初始化时连接池至少创建的空闲连接数量
maxcached: 连接池中允许的最大空闲连接数量。如果设置为0或None,则不会创建
maxshared: 共享连接数,即同时使用的最大数据库连接数(默认为0,表示不共享)
maxusage: 每个连接的最大使用次数,超过该次数则该连接将被关闭并从连接池中移除。如果设置为0或None,则连接池不会关闭连接
reset: 如果设置为True,则在将连接放回池中之前将其重置为其初始状态
blocking: 连接池中在没有可用的连接时,是否等待,如果设置为True,等待,直到有可用连接再分配;如果设置为False,不等待,达到最大连接数时再请求新的连接将抛出异常
failures: 在尝试获取连接时,数据库连接失败后可以尝试重新连接的次数。如果设置为None,则只会尝试一次
ping: 表示是否需要在使用数据库连接之前检查连接的连通性。如果设置为0,则不检查;如果设置为1,则在使用连接之前检查连通性;如果设置为大于1的整数,则会在分配连接之前尝试该次数的数据库连接
host: 表示数据库连接地址
user: 表示数据库连接用户名
password: 表示数据库连接密码
database: 表示数据库名
charset: 表示数据库字符集设置
cursorclass: 表示指定DictCursor(字典)作为游标类
关闭并将连接归还到连接池
# 关闭并将连接归还到连接池
cur.close()
conn.close()
在使用连接池过程中需要注意的是,应该在使用完连接后将其归还到连接池中,以确保可以最大程度地重复使用数据库连接。
如以上的例子,如果在每次从连接池中获取一个连接进行操作,使用完后,不关闭,那么连接池数据达到设置的最大值3后,就无法再使用连接池的连接,并且在使用的时候,会报抛出异常raise TooManyConnections
关闭数据库连接池
# 关闭连接池
pool.close()
如果在调用close()方法时,连接池中仍有活动的连接,则不会立即关闭连接池。相反,它将等待所有连接都被释放后再关闭连接池。
因此,如果调用close()方法后仍然能够从连接池中获得连接,则说明仍然存在活动的连接。在这种情况下,可以等待一段时间,直到所有连接都被释放,并重新尝试调用close()方法。还可以手动释放所有连接,以便更快地关闭连接池。
其实和前面分享的
python对Mysql的增、删、改、查操作
九月de云,公众号:九月de云python对Mysql的增、删、改、查操作,独立封装版
类似,只需要将__init__和connect()部分修改即可,
class PooledDB_tools:
def __init__(self):
self.pool = PooledDB(
creator=pymysql,
maxconnections=None,
mincached=2,
maxcached=3,
maxshared=3,
maxusage=0,
reset=True,
blocking=True,
failures=None,
ping=1,
host='localhost',
user='root',
password='111111',
database='test',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
def connect(self):
"""
启动
:return:
"""
conn = self.pool.connection()
cursor = conn.cursor()
return conn, cursor
源码在文章最后,有兴趣的朋友可自取。
本次以单机写入Mysql为例,分为批量数据写入和单数据写入两类,都采用了本篇的PooledDB(组合pymysql)和前期的pandas(组合sqlalchemy)、pymysql这三种方式写入Mysql。
以下的调用方法中会用到前期分享的类方法:
读取csv_tools.read_csv()
csv操作独立封装
九月de云,公众号:九月de云python将Mysql查询的数据保存到csv文件中,csv操作独立封装
pandas写入,mysql.to_sql()
pandas读写mysql独立版
九月de云,公众号:九月de云python对Mysql数据库的增加和查询操作,pandas独立版
pymysql写入
python对Mysql的增、删、改、查操作,独立封装版
九月de云,公众号:九月de云python对Mysql的增、删、改、查操作,独立封装版
这里不再详述,有需要的去直接下载引用即可!
user_data1.csv
user_data2.csv
user_data3.csv
user_data4.csv
PooledDB方式写入
# -*- coding: utf-8 -*-
import time
from src.csv.csv_tools import csv_tools
from src.mysql_PooledDb.pool_tools import PooledDB_tools
files = ['user_data1.csv', 'user_data2.csv', 'user_data3.csv', 'user_data4.csv']
m = PooledDB_tools()
sql = f'insert into users_msg(name, age, score) values(%s,%s,%s)'
result_ = 0
elapsed_ = 0
for file in files:
ct = csv_tools(file)
data_ = ct.read_csv()[0]
data = list(map(lambda d: (d['name'], d['age'], d['score']), data_))
start_time = time.time()
result = m.insert_many(sql, data)
end_time = time.time()
result_ += result
elapsed = end_time - start_time
elapsed_ += elapsed
print("插入", result_, "条数据!")
print("耗时:{:.2f}".format(elapsed_), "秒")
结果:
插入 2000000 条数据!
耗时:21.67 秒
pandas方式写入
# -*- coding: utf-8 -*-
import pandas as pd
import time
from src.csv.csv_tools import csv_tools
from src.mysql_pandas.tools import mysql_pandas
files = ['user_data1.csv', 'user_data2.csv', 'user_data3.csv', 'user_data4.csv']
t_name = "users_msg"
mp = mysql_pandas()
result_ = 0
elapsed_ = 0
for file in files:
ct = csv_tools(file)
data_ = ct.read_csv()[0]
data = pd.DataFrame(data_)
df = data.drop('id', axis=1)
start_time = time.time()
result = mp.to_sql(t_name, df, 'append')
end_time = time.time()
elapsed = end_time - start_time
elapsed_ += elapsed
result_ += result
print("插入", result_, "条数据!")
print("耗时:{:.2f}".format(elapsed_), "秒")
结果:
插入 2000000 条数据!
耗时:30.97 秒
pymysql写入
# -*- coding: utf-8 -*-
import time
from src.csv.csv_tools import csv_tools
from src.mysql.tools import MysqlTools
files = ['user_data1.csv', 'user_data2.csv', 'user_data3.csv', 'user_data4.csv']
sql = f'insert into users_msg(name, age, score) values(%s,%s,%s)'
result_ = 0
elapsed_ = 0
for file in files:
ct = csv_tools(file)
data_ = ct.read_csv()[0]
data = list(map(lambda d: (d['name'], d['age'], d['score']), data_))
start_time = time.time()
m = MysqlTools()
result = m.insert_many(sql, data)
end_time = time.time()
elapsed = end_time - start_time
elapsed_ += elapsed
result_ += result
print("插入", result_, "条数据!")
print("耗时:{:.2f}".format(elapsed_), "秒")
结果:
插入 2000000 条数据!
耗时:26.67 秒
user_data.csv
PooledDB方式写入
# -*- coding: utf-8 -*-
import time
from src.csv.csv_tools import csv_tools
from src.mysql_PooledDb.pooledbd_tools import PooledDB_tools
ct = csv_tools('user_data.csv')
data_ = ct.read_csv()[0]
data = list(map(lambda d: (d['name'], d['age'], d['score']), data_))
m = PooledDB_tools()
start_time = time.time()
sql = f'insert into users_msg(name, age, score) values(%s,%s,%s)'
for i in data:
m.insert(sql, i)
end_time = time.time()
elapsed = end_time - start_time
result = len(data)
print("插入", result, "条数据!")
print("耗时:{:.2f}".format(elapsed), "秒")
结果:
插入 10000 条数据!
耗时:14.23 秒
pandas方式写入
# -*- coding: utf-8 -*-
import time
import pandas as pd
from src.csv.csv_tools import csv_tools
from src.mysql_pandas.tools import mysql_pandas
mp = mysql_pandas()
t_name = "users_msg"
ct = csv_tools('user_data.csv')
data = ct.read_csv()[0]
start_time = time.time()
result = 0
for i in [[d] for d in data]:
df_ = pd.DataFrame(i)
df = df_.drop('id', axis=1)
result_ = mp.to_sql(t_name, df, 'append')
result += result_
end_time = time.time()
elapsed = end_time - start_time
print("插入", result, "条数据!")
print("耗时:{:.2f}".format(elapsed), "秒")
结果:
插入 10000 条数据!
耗时:240.02 秒
pymysql写入
# -*- coding: utf-8 -*-
import time
from src.csv.csv_tools import csv_tools
from src.mysql.tools import MysqlTools
ct = csv_tools('user_data.csv')
data_ = ct.read_csv()[0]
data = list(map(lambda d: (d['name'], d['age'], d['score']), data_))
sql = f'insert into users_msg(name, age, score) values(%s,%s,%s)'
start_time = time.time()
for i in data:
m = MysqlTools()
m.insert(sql, i)
end_time = time.time()
elapsed = end_time - start_time
result = len(data)
print("插入", result, "条数据!")
print("耗时:{:.2f}".format(elapsed), "秒")
结果:
插入 10000 条数据!
耗时:120.75 秒
综上统计
实践数据,只作参考。综上所述:
使用数据库连接池PooledDB,效率相对较高一些。
其次是直接使用pymsql。
pandas在写入数据库效率较低些,但它本身是主用于数据分析的。
如果在实际使用过程中,Mysql操作尽量使用PooledDB或直接使用pymysql;数据分析操作,再用pandas,合理的配合,会让工作效率更高。
采用Python中的数据库连接池(PooledDB)提供了许多好处,包括:
1. 提高性能:使用连接池可以节省创建和释放连接的开销,并且可以重复使用已经存在的连接。如此可以更快地响应请求,同时减少数据库服务器的负载。
2. 减少资源消耗:由于连接池可以重复使用现有的连接,因此不需要为每个数据库请求创建一个新的连接,并且可以处理更多的并发请求。这意味着应用程序使用的内存和CPU资源更少。
3. 更好的稳定性:由于连接池会自动管理连接的生命周期,并在需要时关闭或重新创建它们,因此可以降低连接泄漏和死锁等风险。
4. 更方便的编程:使用连接池可以使编程变得更加简单明了。您只需从池中获取一个连接,并使用它来执行数据库操作,然后将其释放回池中即可。连接池会处理所有其他的细节,例如创建和释放连接,以及管理连接的生命周期。
综上所述,使用数据库连接池可以带来许多好处。如果大家工作中需要频繁地与数据库进行交互,那么非常值得考虑选择使用数据库连接池。
以上仅代表个人在使用过程中的观点和体会,具体问题仍需要具体考虑。
实践代码做了可公开的简单处理,结构如下:
有需求的朋友可自取哟
获取:后台回复“PooledDB”即可
文章就分享到这儿,喜欢就点个赞吧!