006 Kudu | Schema设计

Kudu有着和RDBMS类似你的结构数据存储机制,Schema的设计非常重要

  1. 读写能够spread到整个tablet servers,而不会出现热点,partition作用
  2. Tablets能够按照均匀,可预测的速度增长,负载平稳
  3. 一次查询,最小的数据访问需求

Column设计

属于Primary Key的列不能为空,支持的数据类型如下

  • boolean
  • 8-bit signed integer
  • 16-bit signed integer
  • 32-bit signed integer
  • 64-bit signed integer
  • unixtime_micros (64-bit microseconds since the Unix epoch)
  • single-precision (32-bit) IEEE-754 floating-point number
  • double-precision (64-bit) IEEE-754 floating-point number
  • decimal
  • UTF-8 encoded string (up to 64KB uncompressed)
  • binary (up to 64KB uncompressed)

Kudu会对列进行高效的编码和序列化,这也是它做列式存储的初衷,因此应该正确使用列的类型,而不是简单一味的全部使用string或者binary。

Decimal Type

该类型是一个数值类型,通过fixed scale和precision,来满足财务或者数学相关数据的表示。都有float和double了,为什么还需要decimal type?
float和double是浮点数,而decimal是定点数,浮点数会出现精确度不高的问题,所以,decimal定点数更多用于财务数字方面。
尽可能使用合适的精度和标度,以减少存储的消耗和计算的消耗。

列编码

编码列表如下,


列编码.png
  1. Plain Encoding,数据按照自有的格式存储,比如,int32的值就按照fixed-size 32-bit little-endian整形进行存储
  2. Bitshuffle Encoding,数据块bit被重新编排,所有值的最重要bit第一位,其次放次重要的bit,以此类推...,最终结果是lz4压缩,该编码适合有很多重复的数值情况,或者当根据primary key进行排序,对应某个数值集合改动很小。
  3. Run Length Encoding,通过存储值value和数量count来对一列进行压缩,适合当对primary key进行排序后,连续重复的数值进行压缩
  4. 构造包含unique values的字典,在字典中存储每列编码后的值和其对应的字典index完成编码工作,对于具有low cardinality的列高效。在对数据进行flush的时候,如果列的unique values的数量过多的话,kudu自动将该编码降解为plain Encoding
  5. Prefix Encoding,前缀编码,对于列值大多数有共同前缀的情况下,使用该编码,对于第一列为主键的列,使用该编码。

列压缩

支持Lz4,Snappy,Zlib。目前lz4最好,bitshuffle-Encoding默认是lz4编码,不需要重复设置。

主键的设计

每个Kudu表必须声明primary key,并且primary key具有唯一性的约束,试图插入一个primary key已经存在的数据,会导致duplicate error。

primary key涉及的列,必须是非空的,不能是boolean,float,double类型(decimal可以),一旦设置完primary key后的表,不能修改primary key。

和RDBMS不同,Kudu不支持自动增加的primary key,因此insert时候,必须提供全部的primary key;同理,修改删除的时候,也需要指明修改删除row对应的全部的primary key,目前,Kudu不支持natively的范围delete和update;虽然Kudu的主键不支持修改,但是可以先删除后插入。

主键索引

Tablet中的所有rows是按照primary key排序的。基于主键的,相等,范围查找,效率高。

Backfill 插入//todo

考虑一个问题,primary key是timestamp或者primary key的第一个列是timestamp,当插入数据时,Kudu会去查找key是否存在,如果存在则duplicate error。

分区

选择一个合适的分区策略需要理解数据模型和table表的负载期望,对于写多的应用场景,能够让写操作spread所有tablet至关重要,这样可以避免某个tablet过大。同样的,对于很多short scans的情况,如果对于scan的数据都在一个tablet上的话,会有更高的效率。上面两点是我们进行分区策略设置需要铭记于心的。

Range分区

Range分区使用全局有序的range分区key来分布数据,每一个分区都被赋予一部分连续的keys,这部分一定会是整体primary key 列的keys的子集。如果没有hash分区参与,对于range分区,一个分成的range分区都是一个tablet。

Range分区必须不能彼此重叠,每个row都只能落在唯一一个分区中。

Range分区可以动态的增加和删除,如果删除一个range分区,则对应的tablet也会删除,数据也会删除,

Hash分区

Hash分区通过hash值将数据分布到多个buckets中,buckets的数量在create表的时候设置好。当不需要顺序访问表的时候,使用hash分区是非常有效的,能有效的将数据spread所有tablets

多级别分区

Hash和Range两种分区,各种好坏,通过结合,能够充分利用二者的优势,当然要结合业务情况。

分区Prune

Kudu能够自动skip扫描所有分区,当他能够对scan语句进行确定是否能够过滤掉某些不需要的分区。对于hash分区,scan扫描能够在每一个hashed列上相等才行,对于range扫描,能够在range partitioned列上进行相等或者范围上判断。

分区的例子

接下来,我们通过例子来说明两种分区的某些特点。考虑如下建表语句,metric表

CREATE TABLE metrics (
    host STRING NOT NULL,
    metric STRING NOT NULL,
    time INT64 NOT NULL,
    value DOUBLE NOT NULL,
    PRIMARY KEY (host, metric, time),
);

Range分区例子

假定,time有2014,2015,2016年的,通常time字段设置range分区,两种方式

  1. unbounded range分区
  2. bounded range分区


    range-partitioning-example.png

在第一个例子中,使用了默认的range分区,将会在2015-01-01和2016-01-01两个点进行分区,这样导致了三个tablets,1)2015-01-01之前,2)2015-01-01到2016-01-01,3)2016-01-01之后,

第二个例子,使用分区范围bounded方式,[(2014-01-01), (2017-01-01)],分割点是2015-01-01,和2016-01-01。最终,分区为,[(2014-01-01), (2015-01-01)], [(2015-01-01), (2016-01-01)], 和[(2016-01-01), (2017-01-01)]

第一个例子是unbounded,第二个是bounded分区。

上述两种方式都支持time-bounded扫描的分区prune(前提是被pruned分区的time bound都落在scan time的bound之外)。对于写操作,上述两种方式都面临着写热点的问题,因此,指标metric写入都是基于当前时间的,大多数写操作都会落入到一个单独range分区中。

Hash分区

假设,我们在host和metric上同时hash


hash-partitioning-example.png

该例子,在host和metric上分成4个buckets,这点不同于range分区,hash分区可以使得write操作spread所有tablets,提高写的吞吐量,同时,scan操作也可以利用分区的prune。

严重的一点是,hash策略会导致每个分区越来越大,因为buckets个数固定了。这点range分区不会,因为range分区可以通过增加新的分区来扩容

Hash和Range结合的例子

先看下二者之间的优缺点。


优缺点.png

Hash分区能够提高写的吞吐量,Range分区能够避免无限的tablet增长问题。所以,通常可以结合两种策略,来利用各自的优点。如下图,


结合的分区方案.png

在time上进行range分区,在host和metric上进行hash分区,结合了hash和range两种策略。写操作会并发到hash buckets的数据,这里是4个buckets,读操作还可利用time bound和明确host以及metric实现分区prune。新的分区也可以添加进来,同时会生成4个新的tablets。

Hash和Range结合的例子

两个hash策略结合,可以不同的buckets


hash-hash-partitioning-example.png

host 4 buckets,metric 3 buckets,总共12个tablet,写操作可以spread所有tablets,读操作可以重复利用host和metric进行分区prune。

缺陷

  • Number of Columns
    By default, Kudu will not permit the creation of tables with more than 300 columns. We recommend schema designs that use fewer columns for best performance.

  • Size of Cells
    No individual cell may be larger than 64KB before encoding or compression. The cells making up a composite key are limited to a total of 16KB after the internal composite-key encoding done by Kudu. Inserting rows not conforming to these limitations will result in errors being returned to the client.

  • Size of Rows
    Although individual cells may be up to 64KB, and Kudu supports up to 300 columns, it is recommended that no single row be larger than a few hundred KB.

  • Valid Identifiers
    Identifiers such as table and column names must be valid UTF-8 sequences and no longer than 256 bytes.

  • Immutable Primary Keys
    Kudu does not allow you to update the primary key columns of a row.

  • Non-alterable Primary Key
    Kudu does not allow you to alter the primary key columns after table creation.

  • Non-alterable Partitioning
    Kudu does not allow you to change how a table is partitioned after creation, with the exception of adding or dropping range partitions.

  • Non-alterable Column Types
    Kudu does not allow the type of a column to be altered.

  • Partition Splitting
    Partitions cannot be split or merged after table creation.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352