索引和主表的唯一区别在于主表一定包含所有的列,而索引通常只包含一部分主表的列。因为索引通常只包含一部分主表的列,所以当一个查询需要访问该索引上不包含的列时,就需要通过索引上的主表主键去主表上找到相关列,这个过程称之为回表。

    为了支持回表,OceanBase 数据库主表的主键列会自动地填充到索引列中。比如用户创建了一个 (a,b) 的联合索引,并且该表的主键是 c, 那么该索引的索引键其实是 (a,b,c)。

    访问路径是指数据库中访问表的方法,既使用哪个索引来访问表。OceanBase 数据库的一个访问路径主要有三个特征来描述。这些特征都可以在计划展示中显示出来,并且这些特征基本上决定了一个访问路径的代价。

    比如我们有一个包含两列的联合索引(a,b), 当用户给了条件 a = 1 and b > 1 的时候,我们可以很快定位到索引扫描开始的位置(从第一个满足a = 1 and b > 1的地方开始扫描)。如果用户给的条件是 a < 5, 我们可以快速定位到扫描结束的位置(既最后一个满足a<5的位置)。这种快速定位的特征可以大大减少访问路径的数据扫描量,从而提升性能。

    如下例所示,其中 range(1,1,MIN ; 1,5,MAX) 定义了下图中的查询扫描开始和扫描结束的位置,该 range 有三个维度分别对用了三个索引列 (a,b,c), 其中 MIN 表示从最小值,MAX 表示最大值。

    该访问路径是否需要回表。如果一个访问路径中包含了该查询所需要的所有列,那么该路径就不需要回表,反之,该路径就需要回表。

    访问路径的谓词计算方式,既哪些谓词可以在索引上计算,哪些谓词需要回表之后才能计算。如果一个谓词涉及到的列都在索引上,那么很显然地,该谓词可以在索引上直接计算,否则该谓词需要回表之后才能进行计算。理论上来说,能够在索引上计算的谓词应该尽量在访问索引的时候进行计算,因为这样可以减少回表的行数。

    对于如下查询例子,该查询有两个谓词 c = 1 and d < 1, filter_before_indexback 这个数组分别对应了该两个谓词的计算形式,true 代表该谓词可以在索引上直接计算,false 代表该谓词需要在回表之后计算。因为k1这个索引包含了 a,b,c 三列,所以很显然谓词 c = 1 可以在索引上直接计算,而谓词 d < 1 需要回表之后才能计算。

    访问路径选择是指数据库中选择访问路径的方法。OceanBase 数据库的路径选择方法融合了基于规则的路径选择方法和基于代价的路径选择方法,OceanBase 数据库首先会使用基于规则的路径选择方法,如果基于规则的路径选择方法之后只有一个可选择的路径, 那么就直接使用该路径,否则就再使用基于代价的路径选择方法选择一个代价最小的路径。

    如下为用 hint 来指定访问路径的示例: