我目前正在开发一个 Discord Python 机器人,我在其中循环遍历
ForumTags
列表,并为每个对象生成
INSERT INTO
SQL 语句以将数据插入 MySQL 数据库。
但是,我想要通过将所有这些单独的
INSERT INTO
语句组合到单个查询中来优化我的代码,如下所示:
INSERT INTO guild_support_tags (guild_id, tag_id, tag_name, category) VALUES
(123, 1, "test", "test_category"), (456, 2, "another tag", "test_category2)
这是我当前的代码:
start = time.time()
for tag in forum.available_tags:
await write_query("INSERT INTO guild_support_tags (guild_id, tag_id, tag_name, category) VALUES "
"(:guild_id, :tag_id, :tag_name, :category)",
{"guild_id": interaction.guild_id, "tag_id": tag.id, "tag_name": tag.name,
"category": category})
print(f"loop done after {time.time() - start}")
# from other file - created by myself to execute MySQL statements
# I would like a solution where this part is untouched. But if it can be improved, its okay.
async def write_query(query: str, params: dict) -> None:
async with async_session() as session:
async with session.begin():
await session.execute(text(query), params)
也许最好知道:我目前使用 SQLAlchemy|| |与 aiomysql 和 Python3.12 在 MariaDB 数据库上。 database.
你可以通过将所有值元组构建为列表,然后使用单个
executemany
调用将它们一次性插入来实现。
start = time.time()
values = []
for tag in forum.available_tags:
values.append((interaction.guild_id, tag.id, tag.name, category))
await write_query("INSERT INTO guild_support_tags (guild_id, tag_id, tag_name, category) VALUES (:guild_id, :tag_id, :tag_name, :category)", values)
print(f"loop done after {time.time() - start}")
# 来自其他文件 - 由我自己创建以执行 MySQL 语句
# 我希望这个部分不受影响地得到一个解决方案。但如果可以改进,也可以。
async def write_query(query: str, params) -> None:
async with async_session() as session:
async with session.begin():
await session.executemany(text(query), params)
这段代码首先构造一个
values
列表,其中包含每个
ForumTag
的元组。然后,它使用
executemany
方法用单个查询将所有值插入数据库。这比在循环中执行单独的
INSERT
语句要高效得多。
另外,请注意,你不需要在
write_query
函数中将
params
作为字典传递。你可以直接传递值列表或元组,因为
executemany
会处理迭代。