概述:Schema 设计主要是 Primary Key,Partition Strategy,Column Type 前二者对性能影响明显后者面向业务。
Column Design:
Type 支持类型:
Boolean,integer,float,double,unixtime,decimal,UTF-8 string,binary
其中decimal类型是精确计算数值使用,可以指定有效位数和有效小数位,在业务可接受情况下,应该尽量使用较小的有效位数,从而减少对性能,内存,存储的负面影响。
且decimal的精确度不能通过更改表的方式改变。
Primary Key Design:
主键:类似于RDBMS中的「主键」,可以由一列或多列共同组成,唯一标记一行,如果插入一个已经存在主键的数据,会报错;创建表的过程中指定主键列,且主键列插入数据是不能为空,不可更改。
在更新或删除数据时需要指定完整主键;kudu本身不支持范围删除,更新;更新主键列可以通过先删除行数据,再进行插入;
主键索引:同一个tablet中的row根据主键排序;在查找数据时按主键的值或者主键的范围进行查找可以提高查找效率。
注意事项:当插入数据时kudu会根据主键来判定表中是否已经有该主键,如果主键中含有timestamp那么需要对比的主键将会变得范围特别小,此时会之间对比缓存中的主键而不访问磁盘,效率非常高
同样因为以上原因,在插入数据的时候需要进行确定数据需要插入的位置以及primaryKey是否已经存在导致在插入历史数据的时候(缓存中没有)会导致插入的速度变慢。
为减少上述情况对性能的影响:1.缩短primaryKey的长度,增加可缓存的主键数量,减少内存使用量
更改主键的结构,使回填写入主键命中连续的范围
Partition Strategy:
分区:为了支持扩展,kudu将数据分配给多个存储单元(tablet,类似hbase的region)
分区设计原则:当数据写入需求较大时应该尽可能将写入的数据分配到多个分区,避免数据热点;当有多个短小扫描需求时远程的链接将成为性能的主导因素,应该将需要读取的数据尽可能集中到相同的tablet。
建议:kudu没有默认分区规则,当数据的读写需求都很大时建议将分区数设置为与 tablelet server相同的数量。
kudu提供两种分区方式:range partitioning,hash partitioning
range partitioning:
范围分区通过分区键的整体排序将分区键连续的部分数据分配到同一个 partition(tablet)
分区键应该是主键的子集,如果范围分区表中没有hash分区那么一个分区一定属于一张表
范围分区管理:分区可以被删除和增加,有利于处理时间序列数据,可以预先设置分区用于存放未来会产生的数据,也可以删除历史时间的数据来提高kudu的效率
hash partitioning:
hash分区是通过建将分区键进行hash然后进行分配bucket
优点:当进行写入操作时hash partition的并行比较好,有利于减少数据热点,提高写入性能
缺点:由于hash分区是创建表的时候指定的,同一张表在持续插入数据的时候会导致tablet不断变大,最终可能会导致一个server放不下一个tablet(可通过搭配range partition策略来解决)
----------------------------------------------------------------------------------------------------------------------------------------------------------------
注释:分区概念中的partition,tablet,bucket的理解。
其中partition是一个概念,tablet是每一个server数据段真正持有的最小单位也就意味着tablet是不可分的;
bucket是hash partition中的概念,若hash partition有两级,第一级分4个bucket,第二级分4个bucket那么最终就会有16个bucket也就对应着16个tablet。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
性能考虑方向:
- 写入数据是尽量分摊压力,避免「热点问题」
- 读取数据是尽量 Scan 少的 Tablet 数量
- 存储数据避免一个 Tablet 过大,导致 Tablet Server 溢出