You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Item外键关联SaleItem性能过慢,寻求优化方案

问题场景与代码

Item 模型

class Item(models.Model):
    title = models.CharField(max_length=100)
    model = models.CharField(max_length=100, blank=True, null=True)
    sku = models.CharField(max_length=100, blank=True, null=True)
    ean = models.CharField(max_length=100, blank=True, null=True)
    price = models.FloatField(blank=True, null=True)
    inventory = models.IntegerField(blank=True, null=True)
    sales_price = models.DecimalField(decimal_places=2, max_digits=15, blank=True, null=True)
    web_shop_price = models.DecimalField(decimal_places=2, max_digits=15, blank=True, null=True)
    bb_price = models.DecimalField(decimal_places=2, max_digits=15, blank=True, null=True)
    discount_price = models.FloatField(blank=True, null=True)
    categorie = models.ForeignKey(Categorie, on_delete=models.CASCADE, null=True, blank=True)
    # slug = models.SlugField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    image = models.ImageField(upload_to='images', null=True, blank=True)

SaleItem 模型

class SaleItem(models.Model):
 
    invoice_id = models.PositiveIntegerField(auto_created=True)
    product = models.ForeignKey(Item, on_delete=models.CASCADE)

当前数据库中已存有15000+条Item数据,在通过SaleItem的外键关联查询或操作时,耗时极长,性能严重下降。使用的是JawsDB 10美元套餐的MySQL数据库,推测除数据量因素外,数据库内存共享也可能是诱因。

优化方案
  • 索引优化:外键字段默认会创建索引,但需确认SaleItem.product的索引是否正常生效。另外,若业务查询常使用Item的特定字段(如sku、title)进行关联或过滤,可为这些字段添加索引:

    # 在Item模型的Meta类中添加索引
    class Item(models.Model):
        # 原有字段...
        class Meta:
            indexes = [
                models.Index(fields=['sku']),
                models.Index(fields=['title']),
            ]
    

    执行迁移后,MySQL会生成对应索引,直接加速关联查询效率。

  • 避免无效查询:检查业务中涉及SaleItem与Item的查询逻辑,杜绝全表扫描:

    • 避免使用__contains这类无法命中索引的模糊查询,改用__startswith;
    • 不要默认查询所有字段,用only()或values()指定所需字段,减少数据传输量:
      # 示例:仅加载必要字段,跳过description、image等大字段
      SaleItem.objects.select_related('product').only('invoice_id', 'product__title', 'product__sku')
      
  • 数据库配置调整:针对JawsDB的共享内存限制,可尝试:

    • 联系服务商调整join_buffer_size和sort_buffer_size参数,提升关联查询的内存分配;
    • 定期归档历史SaleItem数据,减少单表数据体量。
  • 批量操作替代循环单条操作:如果存在批量创建/更新SaleItem的场景,使用Django的bulk_create()和bulk_update()方法,减少数据库交互次数:

    # 批量创建SaleItem示例
    sale_items = [
        SaleItem(invoice_id=1, product=item1),
        SaleItem(invoice_id=1, product=item2),
        # 更多对象
    ]
    SaleItem.objects.bulk_create(sale_items)
    
  • 用select_related解决N+1查询:查询SaleItem时,通过select_related()提前加载关联的Item数据,避免多次数据库请求:

    # 一次查询获取SaleItem及关联的Item数据
    sale_items = SaleItem.objects.select_related('product').all()
    

内容的提问来源于stack exchange,提问作者Sesshōmaru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:21:06