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

如何为Django OR查询创建模型索引以优化性能?

针对该查询的索引优化方案(MySQL 8)

首先拆解你的查询逻辑,它等价于两个独立过滤分支的OR组合:

  • 分支A:is_active=True AND care_over_65=True AND is_provider=False AND (service_care_home=True OR service_home_care=True OR service_live_in_care=True)
  • 分支B:is_active=True AND is_provider=False AND service_retirement_village=True

现有联合索引的问题:包含了查询未用到的-is_premium、name字段,且OR条件的三个service字段位于索引中间,MySQL无法有效利用前缀匹配规则,导致索引失效。

推荐的索引方案

1. 针对分支B的专属联合索引

分支B是固定的三字段等值匹配,直接创建精准匹配的联合索引:

models.Index(
    fields=['is_active', 'is_provider', 'service_retirement_village'],
    name='idx_active_provider_retirement'
)

字段顺序逻辑:将基数最低的布尔字段(is_active、is_provider)放在前缀,MySQL能快速缩小扫描范围。

2. 针对分支A的优化索引

分支A的核心是固定三字段匹配 + 三个service字段的OR判断,有两种可选方案:

方案一:多索引覆盖OR分支(推荐,索引体积小)

为每个service字段创建独立的联合索引,MySQL会自动使用索引合并(Index Merge) 特性处理OR逻辑:

# 覆盖service_care_home的分支
models.Index(
    fields=['is_active', 'is_provider', 'care_over_65', 'service_care_home'],
    name='idx_active_provider_over65_carehome'
)
# 覆盖service_home_care的分支
models.Index(
    fields=['is_active', 'is_provider', 'care_over_65', 'service_home_care'],
    name='idx_active_provider_over65_homecare'
)
# 覆盖service_live_in_care的分支
models.Index(
    fields=['is_active', 'is_provider', 'care_over_65', 'service_live_in_care'],
    name='idx_active_provider_over65_livein'
)
方案二:单覆盖索引(减少索引数量,适合数据量不大的场景)

创建包含所有分支A条件字段的联合索引,MySQL可以通过索引扫描直接判断OR条件(无需回表):

models.Index(
    fields=['is_active', 'is_provider', 'care_over_65', 'service_care_home', 'service_home_care', 'service_live_in_care'],
    name='idx_active_provider_over65_services'
)

额外优化建议

  • 删除原有的全字段联合索引,避免冗余索引占用存储空间、拖慢写入性能。
  • 若查询后需要返回特定字段,可以将这些字段加入索引末尾(覆盖索引),彻底避免回表操作。
  • 用EXPLAIN命令验证索引是否生效:执行EXPLAIN SELECT * FROM your_model WHERE [查询条件],查看type列是否为ref或range,key列是否显示你创建的索引名称。

内容的提问来源于stack exchange,提问作者HenryM

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 12:52:41