如何避免 peewee 对象的 O(n+1) 问题?

问题描述 投票:0回答:1

我在 peewee 有以下模型:

db.py

class Item(BaseModel):
    item_id = IntegerField()
    item_name = CharField()

class Sales(BaseModel):
    sales_id = IntegerField()

class SalesItem(BaseModel):
    sales_item_id = Integer_Field()
    sales = ForeignKeyField(Sales, backref='items')
    item = ForeignKeyField(Item)

视图.py

templates = Jinja2Templates(directory="templates")

def html_get(request, sales_id):
    sales = Sales.get(Sales.sales_id==sales_id)
    return templates.templateResponse('view_sales.html',{'sales':sales})

view_sales.html

Sales: {{ sales.sales_id }}
Items: 
{% for it in sales.items %}
<div>{{ it.item.item_name }}</div>
{% endfor %}

问题是查询

sales = Sales.get(Sales.sales_id==sales_id)
生成 O(n+1) 查询来获取每个项目的名称。我尝试创建连接
sales = Sales.select(Sales,SalesItem,Item).join(SalesItem).join(Item).where(Sales.sales_id==sales_id)
但它也会生成 O(n+1) 查询。

我研究过使用预取,但无法让它工作。知道如何将查询减少到 O(k),其中 k=表的数量吗?

python peewee
1个回答
0
投票

通过这些更新,html_get 函数将通过加入 Sales 和 Item 模型并使用 Prefetch 获取相关数据来仅执行一次查询。这将减少查询数量并提高性能。

def html_get(请求, sales_id): sales_query = Sales.select().where(Sales.sales_id == sales_id) sales_with_items = 预取(sales_query, SalesItem.select().join(Item))

return templates.templateResponse('view_sales.html', {'sales': sales_with_items})
© www.soinside.com 2019 - 2024. All rights reserved.