kudu规范使用

1.kudu设计和使用规范,为数据研发、数据设计人员提供设计的基础参考。

2. Schema设计

Kudu表和关系型数据库的表类似,都有着结构化的数据模型。对于最佳性能和操做的稳定性来说,schema的设计相当重要。没有哪种schema可以适用于全部的表。算法

建立Kudu表时,涉及到列设计、主键设计和分区设计。对于传统的非分布式关系型数据库来说,只有分区是新概念。数据库

3. 优雅的schema

优雅的schema应该具有如下条件:性能优化

数据的读写均匀分布到每一个tablet server,这一点主要受到分区的影响。服务器

tablet可以以稳定、可预测的速率增长,加载的数据保证全天候可用,这主要受到分区的影响。架构

扫描时读取最少的数据量,这一点主要受主键设计的影响,但分区也会起到重要做用。app

好的shema设计依赖于数据特征、对数据操做什么以及集群的拓扑结构。Schema设计对于kudu集群性能最大化来讲是最重要的事情。分布式

4. Column设计

4.1. 数据类型
Kudu表包含多个列,每一个类都有类型,非主键列能够为null。支持的列类型有:ide

布尔
8位有符号整数
16位有符号整数
32位有符号整数
64位有符号整数
unixtime_micros(Unix时代以来的64位微秒)
单精度(32位)IEEE-754浮点数
双精度(64位)IEEE-754浮点数
十进制(详见十进制类型)
UTF-8编码字符串(最多64KB未压缩)
二进制(最多64KB未压缩)
Kudu利用强类型列和列式磁盘存储格式来提供高效的编码和序列化。为了充分利用这些功能,应将列指定为适当的类型,而不是使用字符串或二进制列来模拟“无模式”表。除了编码以外,Kudu还容许在每列的基础上指定压缩。工具

//没有版本和时间戳列 ,同hbase不一样,kudu没有提供version和timestamp列来跟踪行的变化。若是须要的话,须要自行设计一列。oop

4.2. Decimal类型
该类型是具备固定标度和精度适合于金融等算术运算,float与double的不精确表示和舍入行为比较不切实际。该decimal类型对于大于int64的整数和主键中具备小数值的状况也颇有用。

精度:表示列能够表示的总位数,不管小数点的位置如何。此值必须介于1和38之间,而且没有默认值。例如,精度为4表示最大值为9999的整数值,或者表示最多99.99的值,带有两个小数位。您还能够表示相应的负值,而不会

对精度进行任何更改。例如,-9999到9999的范围仍然只须要4的精度。

刻度:表示小数位数。该值必须介于0和精度之间。刻度为0会产生整数值,没有小数部分。若是精度和刻度相等,则全部数字都在小数点后面。例如,精度和刻度等于3的小数能够表示介于-0.999和0.999之间的值。

性能考虑:Kudu将每一个值存储在尽量少的字节中,具体取决于decimal指定的精度。所以,为方便起见,不建议尽量使用最高精度。这样作可能会对性能,内存和存储产生负面影响。

在编码和压缩以前:

精度为9或更小的十进制值以4个字节存储。

精度为10到18的十进制值以8个字节存储。

精度大于18的十进制值以16个字节存储。

alter命令不能修改的列的精度和刻度

4.3. 列编码
能够根据列的类型进行编码。

列类型

编码

默认

int8, int16, int32

plain, bitshuffle, run length

bitshuffle

int64, unixtime_micros

plain, bitshuffle, run ength

bitshuffle

float, double, decimal

plain, bitshuffle

bitshuffle

bool

plain, run length

run length

string, binary

plain, prefix, dictionary

dictionary

4.3.1. Plain encoding
数据以其天然格式存储。例如,int32 值存储为固定大小的32位little-endian整数。

4.3.2. Bitshuffle编码
从新排列一个值块以存储每一个值的最高有效位,而后是第二个最高有效位,依此类推。最后,结果进行LZ4压缩。 若是值重复的比较多,或者按主键排序时值的变化很小,Bitshuffle编码是一个不错的选择。

4.3.3. 运行长度编码
对连续的重复值采用压缩存储,主要是经过只存储值和个数。该编码对按主键排序时具备许多连续重复值的列有效。

4.3.4. 字典编码
建立一个字典存放全部的值,每一个列值使用索引进行编码存储。若是值的个数较少,这种方式比较有效。反之Kudu将透明地回退到该行集的纯编码。这在flush期间进行评估计算。

4.3.5. 前缀编码
在连续的列值中对公共前缀进行压缩。对于有公共前缀的值或主键的第一列或许有效,由于tablet中的行是经过对主键排序存储的。

4.3.6. 列压缩
Kudu容许列使用压缩LZ四、Snappy或zlib压缩编解码器。默认状况下,不进行压缩。若是减小存储空间比原始扫描性能更重要,请考虑使用压缩。

每一个数据集的压缩方式都不一样,但通常来讲LZ4是性能最佳的编解码器,而zlib空间压缩比较大。Bitshuffle编码的列自动使用LZ4压缩,所以不建议在此编码之上应用其余的压缩。

5. 主键设计

每一个Kudu表必须声明由一列或多列组成的主键。与RDBMS主键同样,Kudu主键强制执行惟一性约束。尝试插入具备与现有行相同的主键值的行将致使重复键错误。

主键列必须是非可空的,而且不能够是boolean,float或double类型。

表建立指定主键后,就不能更改。

与RDBMS不一样,Kudu不提供列的自增,所以应用程序必须提供完整的主键。

删除和更新时必须指定完整主键。Kudu自己不支持范围删除或更新。即都是经过主键完成操做。

主键值没法修改。可是,能够删除后从新插入曲线救国。

5.1. 主键索引
与许多传统的关系数据库同样,Kudu的主键是聚簇索引。tablet中的全部行都按主键排序的。 扫描Kudu行时,在主键列上使用相等或范围过滤能够有效地查找行。

5.2. 回填插入的考量
这里考虑主键是时间戳或主键的第一列是时间戳的状况。每次插入,kudu都会主键索引存储区域中查找主键看主键是否存在,若是存在,就返回主键重复错误。若是以数据产生的时间做为主键存储,则热点数据就比较少,执行存在性检查时就会比较快,在内存中就能够命中,不须要走磁盘。

若是是离线的历史数据,每次插入均可能会预冷(主键没法在内存中定位),就会访问磁盘,有时甚至是多个磁盘。正常状况下,kudu能够达到每秒几百万次插入,可是若是是回填数据的话,每秒只能维持几千的插入量。

回填数据的性能优化:

使主键更易压缩
使用固态盘
改变主键结构,使回填主键位于连续的范围中。

6. 分区设计

kudu中的表被分红不少tablet分布在多个tserver上。每一行属于一个tablet。行划分到哪一个tablet有分区决定,分区是在表建立期间设置的。

写入频繁时,考虑将写入动做平衡到全部tablet之间可以有效下降单个tablet的压力,对于小范围扫描操做比较多的状况,若是所扫描的数据都为一个tablet上则能够提升性能。

kudu没有默认分区,建表时,kudu不提供默认的分区策略。建议读写都较重的table能够设置和tserver服务器数量相同的分区数。

kudu提供两种类型的分区:范围分区和哈希分区。表能够有多级分区,组合使用范围和哈希或者多个哈希组合使用。

6.1. 范围分区
Kudu容许在运行时动态添加和删除范围分区,而不会影响其余分区的可用性。删除分区将删除属于该分区中包含的数据。后续插入到已删除的分区中将失败。能够添加新分区,但它们不得与任何现有范围分区重叠。Kudu容许在单个事务更改表操做中删除和添加任意数量的范围分区。

动态添加和删除范围分区对于时间序列特别有用。随着时间的推移,能够添加范围分区以覆盖即将到来的时间范围。例如,存储事件日志的表能够在每月开始以前添加月份分区,以便保存即将发生的事件。能够删除旧范围分区,以便根据须要有效地删除历史数据。

6.2. 哈希分区
哈希分区按哈希值将行分配到存储桶中的一个。在单级散列分区表中,每一个桶只对应一个tablet。在表建立期间设置桶的数量。一般,主键列用做要散列的列,但与范围分区同样,可使用主键列的任何子集。

当不须要对表进行有序访问时,散列分区是一种有效的策略。散列分区对于在平板电脑之间随机写入很是有效,这有助于缓解热点和不均匀的平板电脑大小。

6.3. 多级分区
Kudu容许表在单个表上组合多个级别的分区。零个或多个哈希分区能够与范围分区组合。除了各个分区类型的约束以外,多级分区的惟一附加约束是多级哈希分区不能散列相同的列。

若是使用正确,多级分区能够保留各个分区类型的好处,同时减小每一个分区类型的缺点。多级分区表中的平板电脑总数是每一个级别中分区数的乘积。

6.4. 修剪分区
当经过扫描条件可以彻底肯定分区的时候,kudu就会自动跳过整个分区的扫描。要肯定哈希分区,扫描条件必须包含每一个哈希列的等值断定条件。多级分区表的扫描能够单独利用每一级的分区界定。

7. schema修改

您能够经过如下方式更改表结构:

重命名表
重命名主键列
重命名,添加或删除非主键列
添加和删除范围分区
能够在单个事务操做中组合多个更改步骤。

8. 已知限制

Kudu目前有一些已知的局限性可能会影响到架构设计。

列数
默认状况下,Kudu不容许建立超过300列的表。咱们建议使用较少列的架构设计以得到最佳性能。

cell大小
在编码或压缩以前,单个单元不得大于64KB。在Kudu完成内部复合密钥编码以后,构成复合密钥的单元限制为总共16KB。插入不符合这些限制的行将致使错误返回给客户端。

行的大小
虽然单个单元可能高达64KB,而Kudu最多支持300列,但建议单行不要大于几百KB。

有效标识符
表名和列名等标识符必须是有效的UTF-8序列且不超过256个字节。

主键不可变
Kudu不容许更新主键列。

不可更改的主键
Kudu不容许您在建立表后修改主键列。

不可更改的分区
除了添加或删除范围分区以外,Kudu不容许您在建立后更改表的分区方式。

不可改变的列类型
Kudu不容许更改列的类型。

分区拆分
建立表后,没法拆分或合并分区。

9. 存储限制

kudu单台tablet_server 分区不能超过1500.多台tablet_server 超过1500 则须要进行评估扩容。

tablet server 22台
master 5台
最大数据存储量为,复制和压缩后,每一个tablet server 24TB。
每一个tablet server管理的tablet为1500,包含tablet的副本。
在建立表时,每一个Tablet server的每一个表的最大tablet数为60。

基于以上限制,能够推测出一下内容:

Kudu中存储的总数据量建议为:tablet server总数单个tablet server的数据量=2224TB=528TB/3 =176TB
单个tablet的数据量为:单个tablet server的数据量/每一个tablet server中tablet的总数=24TB/1500=16G。
Kudu支持的压缩方式有LZ4, Snappy,或zlib。鉴于各类压缩算法的压缩比通常不超过50%,则每一个tablet中的数据量在压缩前的大小建议应小于8G。
kudu单表存储最大数量:8亿

10. 生命周期规范

常规表
SUBS层:全部系统的采集数据必须进SUBS层,原则上数据永久存储,可根据实际状况调整(数据量很是大,例如一天数据量大于100 GB),kudu表数据保留12个月(根据实际状况定义),12个月以上的能够转储到hive。

基于kudu存储的数据,根据业务实际需求按照如下定义保留

ODS、DW、DM、ADS层:

当3个月内的最大访问跨度小于或等于4天时,建议将保留天数设为7天。
当3个月内的最大访问跨度小于或等于12天时,建议将保留天数设为15天。
当3个月内的最大访问跨度小于或等于30天时, 建议将保留天数设为33天。
当3个月内的最大访问跨度小于或等于90天时,建议将保留天数设为93天。
当3个月内的最大访问跨度小于或等于180天时, 建议将保留天数设为183天。
当3个月内的最大访问跨度小于或等于365天时,建议将保留天数设为368天。
以上生命周期定义为业界通用定义,能够根据业务实际状况调整。

根据数据域的不一样要求存储,配套相应的冷热数据分离存储方案。

对于时间分区表,根据其数据内容的生命周期,按期删除超出生命周期的分去表

中间表
根据实际状况设置存储周期,原则上存储周期不大于结果表。

备份表
根据实际备份须要设置存储周期。

临时表
临时表的最大生命周期为10天,针对临时表生命周期,应配套相应的检测工具和手段,并在删除前作好相关提示。

11 建表规范

1.hash分区最大不能超过60分区

2.Kudu hash分区建立表例子

CREATE TABLE IF NOT EXISTS [db_name.]table_name

(

id BIGINT PRIMARY KEY COMMENT '注释',

agent STRING COMMENT '注释',

     ...

PRIMARY KEY ( uuid )

)       

PARTITION BY HASH (id) PARTITIONS 4

COMMENT '注释' stored AS kudu;

kudu-混合分区例子:

CREATE TABLE cust_behavior_1 (
id BIGINT,
sku STRING,
salary STRING,
edu_level INT,
usergender STRING,
group STRING,
city STRING,
postcode STRING,
last_purchase_price FLOAT,
last_purchase_date BIGINT,
category STRING,
rating INT,
fulfilled_date BIGINT,
PRIMARY KEY (id, sku)
)
PARTITION BY 
HASH (id) PARTITIONS 4,
RANGE (sku)
(
PARTITION VALUES < ‘g’,
PARTITION ‘g’ <= VALUES < ‘o’,
PARTITION ‘o’ <= VALUES < ‘u’,
PARTITION ‘u’ <= VALUES
) STORED AS KUDU
TBLPROPERTIES(
‘kudu.table_name’ = ‘cust_behavior_1 ‘,’kudu.master_addresses’ = ‘hadoop5:7051’);

时间分区例子:

CREATE TABLE IF NOT EXISTS k_ods_collect_dw_yarn_apps_resource_ds( 
app_id string comment'任务ID', 
use_type string comment'资源使用类别',
name string comment'资源名称',
ds string comment'日汇总', 
resource_type string comment'资源类别',
maximum_allocation bigint comment'最大分配',
minimum_allocation bigint comment'最小分配',
shorthand_representation string comment'快速描述',
units string comment'单位',
value bigint comment'值',
collect_time bigint comment'采集时间',
PRIMARY KEY (app_id,use_type,name,ds))
partition by hash(app_id,use_type,name,ds) partitions 4,
RANGE (ds) (
PARTITION '20201112' <= VALUES < '20210101',
PARTITION '20210101' <= VALUES < '20210201',
PARTITION '20210201' <= VALUES < '20210301',
PARTITION '20210301' <= VALUES < '20210401',
PARTITION '20210401' <= VALUES < '20210501',
PARTITION '20210501' <= VALUES < '20210601',
PARTITION '20210601' <= VALUES < '20210701',
PARTITION '20210701' <= VALUES < '20210801',
PARTITION '20210801' <= VALUES < '20210901',
PARTITION '20210901' <= VALUES < '20211001',
PARTITION '20211001' <= VALUES < '20211101',
PARTITION '20211101' <= VALUES < '20211201',
PARTITION '20211201' <= VALUES < '20220101'
)
COMMENT 'k_ods_collect_dw_yarn_apps_resource_ds'
stored as kudu;
相关文章
相关标签/搜索