EsgynDB如何选择表分区

在分布式数据库中,表分区是一个非常重要的功能。当单表数据量过大,单机节点无法承载时,需要将数据分布到多个节点上。在查询时将查询请求发送到多个节点上,并将返回的查询结果汇总。这是分布式数据库的基本思想。

EsgynDB数据库支持在创建有分区的表,并自动将数据分布到集群的多个节点上去。建表语法为create table xx() salt using N partitions in M regions on (xx)。

Salt using N partitions表示建立有N个分区的表, N可以视作表的逻辑分区数。In M regions表示建立M个hbase region,M可以视作表的物理分区数。通常情况下无需指定表的物理分区数,此时物理分区数和逻辑分区数一致,表上一个逻辑分区就对应hbase中的一个region。

on(xx)表示指定分区键为某一列或几列。如果没有显式指定,则默认分区键为主键。EsgynDB会计算分区键的hash值后来决定数据应该分发到某个分区上。这种做法等同于其他数据库的hash分区。

EsgynDB必须在创建表时指定好分区数和分区键,创建后无法更改。想要用好EsgynDB,给表选择合适的分区是非常重要的一个环节,否则表的性能会很差,无法体现出分布式数据库的性能优势。

首先看分区数,分区数应该选择多少没有特别严格的标准,通常的经验是50万行以下的表无需分区,更大的表选择分区数时应当选择节点数的整数倍。例如集群中有4节点,表上有500万行数据,此时可以选择4个分区或者8个分区都可以。如果表上有1亿行数据,可以选择32分区或者64分区。

通常情况下无需指定表的物理分区数,和逻辑分区数保持一致即可。只有以下两种情况例外:
一是预期这张表以后会写入很多数据,需要提前做好分区。但是目前表上数据并不太多。举个例子,有一张表目前有500万行数据,只需要4个分区即可。但是每天持续写入,预期以后会写入超过1亿行数据,需要提前规划64个逻辑分区。这种情况下随着持续写入,region不断膨胀,hbase自动发生region split导致物理分区数逐渐增加,最终达到较大的物理分区数。二是需要给表开启更高的查询并发度。EsgynDB会自动对分区表的查询开启并发,并发度与表的逻辑分区数有关。例如一张表有500万行数据,建立4个分区后,默认查询时会开启4并发,每个并发去查询一个分区,并汇总数据。如果希望开启16并发提高查询性能,但是又不想让hbase region数太多(每个节点的hbase region数量有一定上限,过高后会导致hbase不太稳定),就可以指定16个逻辑分区,4个物理分区。

接下来看分区键的选择。默认情况下如果用户不显式指定,则默认主键就是分区键。大部分情况下这样也可以,但是有时候这样做会导致性能下降。举例如下:

Create table t1(c1 int, c2 int, c3 int, c4 int, c5 int, primary key(c1,c2)) salt using 8 partitions;
Select * from t1 where c1=?;


主键列为(c1,c2)组合列,查询条件在c1上,如果是不分区的表,此时可以走主键查询,性能非常好。但是由于指定了分区,所以真实的主键列是(salt, c1, c2), 由于只有c1的值,缺少c2的值导致无法计算出salt,因此这条语句就不能走主键查询。虽然由于MDAM优化的存在(EsgynDB的一项优化技术,针对主键组合列首列缺失的情况进行优化),不至于退化成最差的全表扫描,但是性能也是有所下降的。此时最好的做法是指定c1列为分区键,这样可以计算出salt值,有了salt值和c1的值之后,就符合主键查询的条件了,此时性能最好。修改后的建表语句如下:

Create table t1(c1 int, c2 int, c3 int, c4 int, c5 int, primary key(c1,c2)) salt using 8 partitions on (c1);

在选择分区键时还有一个要注意的点是,避免数据不均衡导致热点问题。之前一个真实案例中,简化后的sql如下:

Create table t1(c1 date, c2 int, c3 int, c4 int, c5 int, primary key(c1,c2)) salt using 32 parititions on(c1);
Insert into t1 values(?,?,?,?,?);

这张表c1列是date类型,主键是c1,c2组合列。指定分区键为c1,按照日期进行hash分区。看上去似乎没什么问题。但是每天有接近1000万行数据需要入库,由于是32分区,insert语句会自动开启32并发,每个并发对应一个分区。理论上应该拥有较高的入库性能,但是实际入库性能非常慢。这是由于每天的数据在c1列上是同一天,导致同一天需要入库的数据被hash到同一个分区上去了。这种情况下,尽管开了32并发,实际只有一个并发在干活,其他31个并发没有任何数据,完全空闲。修改成(c1,c2)组合列为分区键后,入库性能立刻有了极大提升。

看到这里有些人可能会疑惑,这个案例的修改跟前一个案例正好倒过来。这样修改不会像上一个案例那样导致查询性能下降吗?事实上这个场景确实也确实有按照日期进行的查询,但是修改后的的查询性能不仅没有下降,反而还提升了许多。问题的关键在于数据量。上一个场景里,根据c1查询的是少量数据甚至是单行数据,此时如果能确定salt值,直接到一个分区上就能完成扫描。而在这个场景下,根据c1日期查询的是数百万行数据,这些数据全部落到一个分区里,所有数据只能在这一个分区里查询,导致热点问题。而修改后,查询的数据均匀落在所有分区里,可以开启32并发去每个分区里扫描并汇总,最终效率远高于修改之前。

Create table t1(c1 date, c2 int, c3 int, c4 int, c5 int, primary key(c1,c2)) salt using 32 parititions on(c1,c2);
Select * from t1 where c1=?;


上面讲的都是对表进行分区。EsgynDB还支持对索引也进行分区,不过索引不能指定分区数和分区键,只能采用和原表一致的分区策略。如果不显式指定,则索引默认不分区。语法如下:

Create index xx on table(col) salt like table;

需要注意的是分区数并非越多越好,尤其是索引是否开启分区,也需要视情况而定。如果节点上hbase region数量已经比较多,hbase负载比较重,对索引开启分区可能会导致region数量过度膨胀,影响hbase稳定性。

EsgynDB提供了强大的表分区功能,但是要用好这个功能,还需要根据业务的实际情况灵活运用。下面附上检查一张表逻辑分区和物理分区是否均匀的方法。建表并导入数据后可以检查以下,如果发现有分布不均匀的情况需要手动修改。最新版本中实现了DDL自动优化建议的功能,也可以使用checkddl命令自动检查一下。检查逻辑分区是否均匀,salt值表示分区,后面是每个分区的数据量。

>>select "_SALT_",count(*) from t1 group by 1;

_SALT_      (EXPR)              
----------  --------------------

         0                 25113
         1                 24964
         2                 24882
         3                 25041

--- 4 row(s) selected.


查看物理分区的分布情况,如下说明46,47,48节点分别有一个hbase region。

>>get region stats for table t1;


Stats Summary
=============

  ObjectName:              TRAF_RSRVD_3:TRAFODION.SEABASE.T1
  NumRegions:              3
  RegionsLocation:         /hbase/data/default
  TotalNumStores:          3
  TotalNumStoreFiles:      0
  TotalUncompressedSize:   0
  TotalStoreFileSize:      0
  TotalMemStoreSize:       0
  TotalReadRequestsCount:  0
  TotalWriteRequestsCount: 0

Stats Details
=============

  RegionServer:       esgyndb-perf47:60020
  RegionNum:          1
  RegionName:         TRAF_RSRVD_3:TRAFODION.SEABASE.T1/1660557226997
  NumStores:          1
  NumStoreFiles:      0
  UncompressedSize:   0 (less than 1MB)
  StoreFileSize:      0 (less than 1MB)
  MemStoreSize:       0 (less than 1MB)
  ReadRequestsCount:  0
  WriteRequestsCount: 0

  RegionServer:       esgyndb-perf48:60020
  RegionNum:          2
  RegionName:         TRAF_RSRVD_3:TRAFODION.SEABASE.T1/1660557226997
  NumStores:          1
  NumStoreFiles:      0
  UncompressedSize:   0 (less than 1MB)
  StoreFileSize:      0 (less than 1MB)
  MemStoreSize:       0 (less than 1MB)
  ReadRequestsCount:  0
  WriteRequestsCount: 0

  RegionServer:       esgyndb-perf46:60020
  RegionNum:          3
  RegionName:         TRAF_RSRVD_3:TRAFODION.SEABASE.T1/1660557226997
  NumStores:          1
  NumStoreFiles:      0
  UncompressedSize:   0 (less than 1MB)
  StoreFileSize:      0 (less than 1MB)
  MemStoreSize:       0 (less than 1MB)
  ReadRequestsCount:  0
  WriteRequestsCount: 0


--- SQL operation complete.


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值