首页 > 数据库 > > TiDB 源代码学习: ranger 模块代码分析
对数据库技术有一定了解的同行们,应该对 索引前缀匹配 的概念不陌生. 在 TiDB 中 ranger 模块在前缀匹配机制中发挥了一定的作用,所以我想好好了解一下这个模块的代码.
ranger 模块重要的入口是 DetachCondAndBuildRangeForIndex 以及 DetachCondAndBuildRangeForTable 两个函数.
本文以 DetachCondAndBuildRangeForIndex 函数为主要的分析对象,下面简称这个函数位 DCBR
DCBR 的入参是:
它的作用可以细分为 3 点:
举个简单例子,假如现在有一个表:
create table (a int, b int, c int, index idx_ab(a, b));我们用下面这条查询语句进行查询:
select * from t where a = 1 and b > 2 and c = 3;系统在衡量使用索引 idx_ab 扫描的效率时,会调用 DCBR 方法计算 ranges, DCBR 得到的入参是:
DCBR 方法执行过程中:
需要补充的是, 即使索引是 (a, b, c), c 列也无法用在索引扫描,这也是前缀匹配原则的缘故.
对于像上面提到的这个例子 a = 1 and b > 2 and c = 3, 查询条件比较简单,所以代码中很多特殊的处理逻辑并没有起作用,具体步骤:
除了支持上面例子中的简单查询条件(也就是多个条件用 and 串联的情况). DCBR 函数还要支持从多个 and/or 组合的条件中提取 accessConds,计算ranges.比如下面这个语句:
select * from t where (a > 1 and a < 3) or (a > 5 or a < );需要补充说明的是,数据库会采用树形结构来表示查询条件,这个 sql 中,查询条件会组成下面这样的树形结构.
处理这类既有 and 又有 or 的查询条件.会先对条件进行一个 flatten 处理.
flatten 操作会把能够提升层级的 or 节点提升上来,经过 flatten 处理以后,会得到一个条件数组, 本次sql的处理结果是 (a > 1 and a < 3) , a > 2 , a < 10 这三个条件组成的数组
完成 flatten 处理以后,会分别计算数组中每个条件的 accessConds 和 ranges, 计算方式和最开头的简单查询条件的计算方式基本一样.然后把得到的 accessConds 和 ranges 合并,会计算ranges 的并集作为最终的 ranges 结果.
最终得到的 range 结果 (-inf, 0), (1, 3), (5, +inf),为了方便理解,这里只给出了 a 列的范围.
有的时候查询条件可能直接可以计算为 false,比如 a > 10 and a < 1;还有 a = 1 and a = 2, ranger 在计算过程中,如果发现某一列的条件计算结果是 false,就会终止整个计算过程,返回空的 ranges.
如果是简单的查询条件, accesssConds 和 filterConds 其实很容易分辨,而且彼此互补影响的.但是对于复杂场景 filterConds 就比较难以提取了.
比如下面这个例子:
select * from t where (a > 1 and a < 2 and c > 10) or (a > 5 or a < );和前面提到的例子相比,查询条件当中多了 c > 10 这个条件. accessConds 并没有发生变化.但是 filterConds 不再为空,而是多了 (a > 1 and a < 2 and c > 10) 这个条件.
ranger 如果在解析 accessConds 时,发现除了解析出来的 accessConds,还剩余了其他条件,这个时候会把整个条件加入到 filterConds 中.
回到这个例子里,ranger 在处理 (a > 1 and a < 2 and c > 10) 这个条件的时候,能够提取出来作为 accessConds 的是 a > 1, a < 2 这两个条件,但是还剩下一个 c > 10 ,这时 ranger 就会把整个 a > 1 and a <2 and c > 10 作为一个 filterConds 保留.
关于 ranger 这块的逻辑,大家可以看一下 TiDB 中提供的 测试用例Range ,里面除了上面描述的场景为还包含了其他一些场景的测试用例:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3166568/ ,如需转载,请注明出处,否则将追究法律责任。