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中如何优化数据库查询以减少匹配次数

6 回复

一次循环就完成的事,需要这么复杂? 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. 用对索引 这步在数据库层面。对你经常用WHEREORDER BYJOIN的字段建索引。比如:

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]

这个确实简化了不少 另外结合求交集

回到顶部