phoenix预创建表拆分key的源码分析

phoenix预创建表的源码分析

下面主要分析了普通物理表,索引表和salt表创建时的预分区情况

在 ConnectionQueryServicesImpl.createTableInternal 方法当中,要分析表是否需要预先分区,

if (parent != null && tableType == PTableType.INDEX && indexType == IndexType.LOCAL) {
        //如果是本地索表则拿到拿到物理数据表的所有region所在的regionserver,
            tableProps.put(MetaDataUtil.PARENT_TABLE_KEY, parent.getPhysicalName().getString());
            tableProps.put(MetaDataUtil.IS_LOCAL_INDEX_TABLE_PROP_NAME, Boolean.TRUE);
            splits = getSplitKeys(connection.getQueryServices().getAllTableRegions(parent.getPhysicalName().getBytes()));
        } else {
            splits = SchemaUtil.processSplits(splits, pkColumns, saltBucketNum, connection.getQueryServices().getProps().getBoolean(
                    QueryServices.FORCE_ROW_KEY_ORDER_ATTRIB, QueryServicesOptions.DEFAULT_FORCE_ROW_KEY_ORDER));
        }

可以看到上面,如果是一个本地的索引表,则调用如下方法,拿到父的物理数据表,所在那个regionserver中,因为索引表的region要与数据表的region同在一个regionserver上(相同的key区间)

connection.getQueryServices().getAllTableRegions(parent.getPhysicalName().getBytes()

 List<HRegionLocation> locations = Lists.newArrayList();
byte[] currentKey = HConstants.EMPTY_START_ROW;
do {
  HRegionLocation regionLocation = connection.getRegionLocation(
  TableName.valueOf(tableName), currentKey, reload);
  locations.add(regionLocation);
  currentKey = regionLocation.getRegionInfo().getEndKey();
} while (!Bytes.equals(currentKey, HConstants.EMPTY_END_ROW));
return locations;

上面的是查看该父表具有那些region,

private byte[][] getSplitKeys(List<HRegionLocation> allTableRegions) {
    if(allTableRegions.size() == 1) return null;
    byte[][] splitKeys = new byte[allTableRegions.size()-1][];
    int i = 0;
    for (HRegionLocation region : allTableRegions) {
        if (region.getRegionInfo().getStartKey().length != 0) {
            splitKeys[i] = region.getRegionInfo().getStartKey();
            i++;
        }
    }
    return splitKeys;
}

上面方法就可以拿出全部的region的startkey了,就可以知道爷的物理数据表的key的区间情况了
如果不是本地索引表。则调用如下方法

// Given the splits and the rowKeySchema, find out the keys that 
public static byte[][] processSplits(byte[][] splits, LinkedHashSet<PColumn> pkColumns, Integer saltBucketNum, boolean defaultRowKeyOrder) throws SQLException {
    // FIXME: shouldn't this return if splits.length == 0?
    if (splits == null) return null;
    // We do not accept user specified splits if the table is salted and we specify defaultRowKeyOrder. In this case,
    // throw an exception.
    if (splits.length > 0 && saltBucketNum != null && defaultRowKeyOrder) {
        throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_SPLITS_ON_SALTED_TABLE).build().buildException();
    }
    // If the splits are not specified and table is salted, pre-split the table. 
    //如果没有指定拆分主键,并且是一个salted类型的表,刚自动生成 saltBucketNum 个预拆分区间
    if (splits.length == 0 && saltBucketNum != null) {
        splits = SaltingUtil.getSalteByteSplitPoints(saltBucketNum);
    }
    byte[][] newSplits = new byte[splits.length][];
    for (int i=0; i<splits.length; i++) {
        newSplits[i] = processSplit(splits[i], pkColumns); 
    }
    return newSplits;
}

//该方法就是很核心的salted类型表的主键前缀拆分的过程了
public static byte[][] getSalteByteSplitPoints(int saltBucketNum) {
    byte[][] splits = new byte[saltBucketNum-1][];
    for (int i = 1; i < saltBucketNum; i++) {
        splits[i-1] = new byte[] {(byte) i};
    }
    return splits;
}

可以看到,上面先是判断该表是不是索引表,如果是就根据父的物理表的存放当前情况,拿出各个region 的location 的位置信息,拿出该区间的startKey,然后生成splits对象。否则调用 processSplit 方法生成 ,里面进行salt表的判断,如果是就直接生成相应的 saltBucketNum个预拆分区间,以指定char类型的byte对象开头的splits。

总结

  1. 根据是一个本地索引表,然后根据父的物理表的当前的region location的startkey 进行拆分成同样多的索引区间
  2. 如果是一个Salte表,根据传进来的saltBucketNum 数量,拆分成指定数量的预拆分region
  3. 根据外面传进来的slplits进行相应的拆分
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值