如何高效实现MySQL版本链表的无冗余启用记录查询
解决方案
这问题我熟,刚好之前也处理过类似的版本迭代表结构优化需求,给你一个完全符合要求的高效SQL查询:
SELECT r.* FROM `records` r LEFT JOIN `records` r_ref ON r.id = r_ref.`ref` WHERE r.type = 2 AND r_ref.id IS NULL;
逻辑解释
我们的核心思路是利用ref字段的特性:最新版本的记录永远不会被其他记录的ref字段指向——因为每次新增同类型的新版本时,只会让新版本的ref指向旧版本,不会有任何记录把最新版本的ID作为自己的ref值。
通过左连接关联自身表,我们把当前记录r和所有以r.id为ref的记录r_ref关联起来:
- 如果
r是旧版本,一定会有至少一条记录(它的下一个版本)的ref等于r.id,此时r_ref.id不为空; - 如果
r是最新版本,没有任何记录会引用它的ID,所以左连接后r_ref.id会是NULL,这就对应了原查询中enabled='1'的结果。
性能保障
要确保这个查询和原查询一样高效(耗时<1ms),你的现有索引已经足够支撑:
- 表上的
type索引会快速筛选出所有type=2的记录; ref字段的索引会加速左连接时的匹配过程,避免全表扫描。
如果想要进一步优化,可以创建一个复合索引(type, id),让筛选type=2和后续的连接操作更高效,但仅靠现有索引已经能满足性能要求。
验证例子
用你给出的第三次迭代后的表数据测试:
- type=2的记录有ID2、4、5;
- ID2被ID4的
ref指向,ID4被ID5的ref指向,只有ID5没有被任何记录的ref引用; - 执行上述SQL会返回ID5的记录,和原查询
SELECT * FROM records WHERE type='2' AND enabled='1'的结果完全一致。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

