查看 mysql range optimization 有对Range Query
的解释。其中有这样的描述,是针对联合索引的,这里截取其中的原文:
For the following expression, the optimizer uses = from the first comparison. It also uses >= from the second comparison but considers no further key parts and does not use the third comparison for interval construction:
针对的sql语句是:
# index(key_part1,key_part2,key_part3)
where key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10
很好奇,从大的方向上来思考,获取二叉树某个范围内的数据,比较快的方式,可能是这样的:
当然,这张图也是盗得,原图的地址在范围搜索 (Range Query)这里。针对MySQL数据库来说,当然也可以这么做了,详细的分成几步来解释:
- 从root节点到图中的u节点,称为路径左
- 从root节点到图中的v节点,称为路径右
- 然后找到路径左和路径右的交点,称为交点
- 过滤从交点到u节点的所有右集合的子节点,称为右集合
- 过滤从交点到v节点的所有左集合的子节点,称为左集合
- 将左集合和右集合的多有叶子节点做并集
真实的MySQL是怎么做的呢,再盗一张图,都有点汗颜💧了,原图的地址在这里:RDBMS架构:B+树实现范围查询(Range Scan),
我抱着怀疑的态度,还是去找了找官方的解释,二叉树为什么不并行的去搞起来呢?还是开头的地址,MySQL版本是5.6。原文有这么一句话,也不知道是不是答案:
MySQL does not support merging multiple ranges for the range access method for spatial indexes.
其实,从开始工作到现在,马上也接近6年了。从开始接触MySQL索引的时候,当时有一个概念一直记到现在:
联合索引的范围查询,当遇到第一个比较操作的时候,后续的索引就用不到了
我也不知道是否描述清楚了,原来这个规则一直没有变化。
在查询的时候,还发现一个有趣的描述,MongoDB范围查询的索引优化,这次不盗图了,因为它没图可以盗。
也当作一个思考题
当查询是:
db.test.find({a:1,b:2}).sort({c:1})
那么直接建立 {a:1, b:1, c:1} 或者 {b:1, a:1, c:1} 的联合索引即可。
如果查询是:
db.test.find({a:1,b:{$in:[1,2]}}).sort({c:1})
那么可能建立 {a:1, c:1, b:1} 的联合索引会比较合适。
下面是一个神奇的公众号,关注他就对了