Python中如何优化数据库查询以减少匹配次数
需求如下: 两组数据: goods 数据是数据库查询出来的一组数据,
goods = Pay.query.filter_by(state=4).all()
good_ids = []
for good in goods:
good_ids.append(good['id'])
b 数据是其他地方获取的数据:
b = {
"t_id_1": {
id = "1",
name = 'name1'
},
"t_id_2": {
id = "2",
name = 'name2'
},
"t_id_3": {
id = "3",
name = 'name3'
},
"t_id_4": {
id = "4",
name = 'name4'
},
"t_id_5": {
id = "5",
name = 'name5'
},
"t_id_6": {
id = "6",
name = 'name6'
},
"t_id_7": {
id = "7",
name = 'name7'
}
}
如果 goods_id 中有的 数字和 b 里面的 id 数字对应,输出 对应的 name,这个如何操作比较好啊,我的方式如下:
for item in b:
for good_id in good_ids:
if good_id == b[item]['id']:
print(b[item]['name'])
请教下如何一次性比较后一次性输出打印结果比较好呢. 我的写法好啰嗦
Python中如何优化数据库查询以减少匹配次数
一次循环就完成的事,需要这么复杂? b 的结构太迷了,不能提出来 id:name 吗?
在Python里优化数据库查询,核心思路就一个:让数据库少干活,把能算的都算在数据库里,别把数据全拉到Python里再处理。
1. 核心原则:用WHERE,别用IF
这是新手最容易犯的错。过滤条件一定要写在SQL的WHERE子句里,而不是把数据全查出来再用Python的if去筛。
# 错误做法:拉取全部数据到内存再过滤
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
all_users = cursor.fetchall()
active_users = [user for user in all_users if user[4] == 'active'] # 在Python里过滤
# 正确做法:让数据库过滤
cursor.execute("SELECT * FROM users WHERE status = 'active'")
active_users = cursor.fetchall() # 直接拿到目标数据
2. 只拿你需要的列
别动不动就SELECT *。明确列出需要的字段,减少网络传输和内存占用。
# 不好
cursor.execute("SELECT * FROM orders")
# 好
cursor.execute("SELECT order_id, customer_name, amount FROM orders WHERE date > '2023-01-01'")
3. 善用JOIN和子查询,避免N+1查询 这是ORM(比如Django ORM、SQLAlchemy)里常见的坑。要一次性关联查询,别在循环里单条查。
# 错误做法(伪代码,以Django ORM为例):N+1查询
books = Book.objects.all()
for book in books:
author_name = book.author.name # 每条Book记录都单独发一次查询去取Author
# 正确做法:使用select_related或prefetch_related一次性关联
books = Book.objects.select_related('author').all() # 使用JOIN一次性取出
for book in books:
author_name = book.author.name # 这里没有额外查询
4. 用对索引
这步在数据库层面。对你经常用WHERE、ORDER BY、JOIN的字段建索引。比如:
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_orders_date ON orders(date);
用EXPLAIN(或EXPLAIN ANALYZE)看你的查询有没有用到索引。
5. 用LIMIT分页,别一次性查太多 特别是网页应用,一定要分页。
page = 1
page_size = 50
offset = (page - 1) * page_size
cursor.execute("SELECT * FROM products ORDER BY created_at DESC LIMIT ? OFFSET ?", (page_size, offset))
6. 考虑用聚合查询代替Python计算
比如求和、计数、平均值,用SQL的SUM(), COUNT(), AVG(),别把数据拉回来自己算。
# 不好
cursor.execute("SELECT amount FROM sales")
total = sum(row[0] for row in cursor.fetchall())
# 好
cursor.execute("SELECT SUM(amount) FROM sales")
total = cursor.fetchone()[0]
总结一下:
- 过滤、排序、分组、聚合这些事,尽量用SQL在数据库端完成。
- 只查询必要的字段。
- 利用好索引(数据库表设计时就要考虑)。
- 避免N+1查询(使用ORM时要特别注意)。
- 大数据集要分页。
一句话建议:把计算推到数据库,让数据在本地“瘦身”后再传输。
改用集合( set ),求一下交集?
x = dict(b)[‘t_id_{}’.format(id)].get(‘name’,None) if dict(b).has_key([‘t_id_{}’.format(id)]) else None
瞎写的,没审题
good_ids = [good[‘id’] for good in goods]
names = [item[“name”] for item in b.values() if item[“id”] in good_ids]
这个确实简化了不少 另外结合求交集

