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

SQLite Explain Query Plan未显示完整步骤的三类技术疑问

SQLite左外连接查询计划疑问解答

1. 为何第一个执行计划未显示SCAN Child?

单独查询SELECT * FROM Child WHERE some_int = 0时的全表扫描,是因为没有索引能直接定位some_int=0的行,只能遍历整张表。但在左外连接的查询中,SQLite的执行逻辑是:

  • 先通过Person的覆盖索引获取每条记录的childId
  • 对非NULL的childId,用Child的主键索引(sqlite_autoindex_Child_1)精准定位到对应行
  • 最后对找到的Child行做some_int=0的行级过滤

这个过滤是在精准定位单条行之后的字段检查,不属于全表扫描(SCAN)范畴,因此执行计划不会单独列出SCAN Child步骤。

2. 为何对Person表是SCAN而非SEARCH?

你的查询条件Person.childId IS NULL OR Child.some_int = 0无法转换为Person表索引可直接用于精准搜索的规则:

  • Person.childId IS NULL需要找出所有childId为空的Person记录,无法通过索引做范围或精准匹配,只能遍历索引条目
  • Child.some_int=0是关联表的条件,无法映射到Person表的索引上做前置筛选

而Person_childId是覆盖索引(包含查询所需的childId字段,无需回表读取Person的其他字段),因此SQLite选择全量扫描该覆盖索引的所有条目,而非执行SEARCH。

3. 该执行计划是否高效,是否需要添加索引?

效率取决于数据规模和分布:

  • 若两张表数据量都很小,当前计划性能完全够用,无需额外索引
  • 若数据量较大,建议给Child表创建联合索引(childId, some_int):
    该索引能让SQLite通过childId查找Child行时,直接在索引内完成some_int=0的判断,无需回表读取Child完整行,减少IO开销
  • 若Person表极大且childId IS NULL的记录占比极低,可拆分查询:分别统计Person.childId IS NULL的数量,以及Person JOIN Child ON Person.childId=Child.childId WHERE Child.some_int=0的数量,再将结果相加。这种方式可利用索引分别优化两个子查询的效率

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:10:52