数据划分
基本概念
Row&Column
一张表包含行(Row)和列(Column).
Column可以分为两大类:Key和Value.
Tablet & Partition
- 在Doris的存储引擎中,用户数据被水平划分为若干个数据分片(Tablet,也称作数据分桶).每个Tablet包含若干数据行.各个Tablet之间的数据没有交集,并且在物理上是独立存储的.
- 多个Tablet在逻辑上归属于不同的分区(Partition).一个Tablet只属于一个Partition.而一个Partition包含若干个Tablet.因为Tablet在物理上是独立存储的,所以可以视为独立存储的,所以可以视为Partition在物理上也是独立.Tablet是数据移动、复制等操作的最小物理存储单元.
- 若干个Partition组成一个Table.Partition可以视为逻辑上最小的管理单元.数据的导入与删除,都可以或仅能针对一个Partition进行.
数据划分
列定义
- AGGREGATE KEY数据模型中,所有没有指定聚合方式(SUM、REPLACE、MAX、MIN)的列视为Key列.而其余则为Value列.
- 定义Key列时,可参照如下建议:
- Key 列必须在所有 Value 列之前。
- 尽量选择整型类型。因为整型类型的计算和查找比较效率远高于字符串。
- 对于不同长度的整型类型的选择原则,遵循 够用即可。
- 对于 VARCHAR 和 STRING 类型的长度,遵循 够用即可。
- 所有列的总字节长度(包括 Key 和 Value)不能超过 100KB。
分区与分桶
- Doris支持两层的数据划分.第一层是Partiton,支持Range和List的划分方式.第二层是Bucket(Tablet),仅支持Hash的划分方式.
- 也可以仅使用一层分区.使用一层分区时,只支持Bucket划分.
- Partition
- Partition列可以指定一列或多列.分区类必须为KEY列.
- 不论分区列是什么类型,在写分区值时,都需要加双引号.
- 分区数量理论上没有上限.
- 当不使用Partiton建表时,系统会自动生成一个和表明同名的,全值范围的Partition.该Partition对用户不可以见,并且不可删改.
Range分区
- 分区列通常为时间列,以方便管理新旧数据.
- Partition支持通过
VALUES LESS THAN(...)
仅指定上界,系统会将前一个分区的上界做为该分区的下界,生成一个左闭右开的区间.通过,也支持通过VALUES [...)
同时指定上下界,生成一个左闭右开的区间. - 当使用
VALUES LESS THAN(...)
语句进行分区的增删操作时,分区范围的变化情况:- 分区的删除不会改变已存在分区的范围.删除分区可能出现空洞,通过
VALUES LESS THAN
语句增加分区时,分区的下界紧接上一个分区的上界. - 不可添加范围重叠的分区.
- 分区的删除不会改变已存在分区的范围.删除分区可能出现空洞,通过
List分区
- 分区列支持
BOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、DATE、DATETIME、CHAR、VARCHAR
数据类型,分区值为枚举值.只有当数据为目标分区枚举值其中之一时,才可以命中分区. - PARTITION支持通过
VALUES IN (...)
来指定每个分区包含的枚举值. - 不可添加范围重叠的分区.
- Bucket
- 如果使用了Partiton,则
DISTRIBUTED...
语句描述的是数据在各个分区内的划分规则.如果不使用Partition,则描述的是对整个表的数据的划分规则. - 分桶列可以是多列,但必须为Key列.分桶列可以和Partition列相同或不同.
- 分桶列的选择,是在查询吞吐和查询并发之间的一种权衡:
- 如果选择多个分桶列,则数据分布更均匀.(适合大吞吐底并发的查询场景)
- 如果仅选择一个或少数分桶列,则对应的点查询仅可以触发一个分桶扫描.(适合高并发)的点查询场景.
- 分桶的数量理论上没有上限.
- 关于Partition和Bucket的数量和数据量的建议
- 一个表的Tablet总数量等于(Partition num * Bucket num).
- 一个表的Tablet数量,在不考虑扩容的情况下,推荐略多于整个集群的磁盘数量.
- 单个Tablet的数据量理论没有上下界,但建议在1G-10G的范围内.如果单个Tablet数据量过小,则数据的聚合效果不佳,且原数据管理压力大.如果数据量过大,则不利于副本的迁移、补齐,且会增加Schema Change或者Rollup操作失败重试的代价(这些操作失败重试的粒度是Tablet).
- 当Tablet的数据量原则和数量原则冲突时,优先考虑数据量原则.
- 在建表时,每个分区的Bucket数量统一指定.但是在动态增加分区时(
ADD PARTITION
),可以单独指定新分区的Bucket数量.可以利用这个功能方便的应对数据缩小或膨胀. - 一个Partition的Bucket数量一旦指定,不可更改.所以在确定Bucket数量时,需要预先考虑集群扩容的情况.
PROPERTIES
在建表语句的最后PROPERTIES中,可以指定一下两个参数:
-
replication_num
- 每个Tablet的副本数量.默认为3,建议保持默认即可.在建表语句中,所有的Partition中的Tablet副本数量统一指定.而在增加新分区时,可以单独指定新分区中Tablet的副本数量.
- 副本数量可以在运行时修改.强烈建议保持奇数.
- 最大副本数量取决于集群中独立IP的数量(注意不是BE数量).Doris中副本分布的原则是不允许同一个Tablet的副本分布在同一台物理机上,而识别物理机即通过IP.所以,即使在同一台物理机上部署3个或更多BE实例,如果这些BE的IP相同,则依然只能设置副本数为1.
- 对于一些小,并且更新不频繁的维度表,可以考虑设置更多的副本数,这样在Join查询时,可以有更大的概率进行本地数据Join.
-
storage_medium & storage_cooldown_time
- BE的数据存储目录可以显式指定为SSD或者HDD(通过.SSD或者.HDD后缀区分).建表时,可以统一指定所有Partition初始存储的介质.注意,后缀的最用时显示指定磁盘介质,而不会检查是否与实际介质类型复合.
- 默认出事存储介质可以通过fe的配置文件
fe.conf
中指定default_storage_medium = xxx
,如果没有指定,则默认HDD.如果指定为SSD,则数据初始存放在SSD上. - 如果没有指定storage_cooldown_time,则默认30天后,数据会自动从SSD自动迁移到HDD上,如果指定了storage_cooldown_time,则在到达storage_cooldown_time时间后,数据才会迁移.
- 注意,当指定storage_medium时,如果FE参数
enable_strict_storage_medium_check
为False
该参数只是一个“尽力而为”的设置,即使集群里没有设置SSD存储介质,也不会报错,而是自动存储在可用的数据目录中.同样,如果SSD介质不可访问、空间不足,都可能导致数据初始直接存储在其他可用介质上.而数据到期迁移到HDD时,如果HDD介质不可访问、空间不足,也可能导致迁移失败.如果FE参数enable_strict_storage_medium_check
则当集群没有SSD存储介质时,会报错Failed to find enough host in all backends with storage medium is SSD
ENGINE
在Doris中,只有olap是由Doris负责数据管理和存储的.其他ENGINE类型,如mysql、broker、es等等,本质上只是对
外部其他数据库或系统中的表的映射.
常见问题
建表操作常见问题
-
如果在较长的建表语句中出现语法错误,可能会出现语法错误提示不全的现象。这里罗列可能的语法错误供手动纠错:
- 语法结构错误。请仔细阅读 HELP CREATE TABLE;,检查相关语法结构。
- 保留字。当用户自定义名称遇到保留字时,需要用反引号 `` 引起来。建议所有自定义名称使用这个符号引起来。
- 中文字符或全角字符。非 utf8 编码的中文字符,或隐藏的全角字符(空格,标点等)会导致语法错误。建议使用带有显示不可见字符的文本编辑器进行检查。
-
Failed to create partition [xxx] . Timeout
- Doris 建表是按照 Partition 粒度依次创建的。当一个 Partition 创建失败时,可能会报这个错误。即使不使用 Partition,当建表出现问题时,也会报 Failed to create partition,因为如前文所述,Doris 会为没有指定 Partition 的表创建一个不可更改的默认的 Partition。
- 当遇到这个错误是,通常是 BE 在创建数据分片时遇到了问题。可以参照以下步骤排查:
- 在 fe.log 中,查找对应时间点的 Failed to create partition 日志。在该日志中,会出现一系列类似 {10001-10010} 字样的数字对。数字对的第一个数字表示 Backend ID,第二个数字表示 Tablet ID。如上这个数字对,表示 ID 为 10001 的 Backend 上,创建 ID 为 10010 的 Tablet 失败了。
- 前往对应 Backend 的 be.INFO 日志,查找对应时间段内,tablet id 相关的日志,可以找到错误信息。
- 以下罗列一些常见的 tablet 创建失败错误,包括但不限于:
- BE 没有收到相关 task,此时无法在 be.INFO 中找到 tablet id 相关日志。或者 BE 创建成功,但汇报失败。以上问题,请参阅 [部署与升级文档] 检查 FE 和 BE 的连通性。
- 预分配内存失败。可能是表中一行的字节长度超过了 100KB。
- Too many open files。打开的文件句柄数超过了 Linux 系统限制。需修改 Linux 系统的句柄数限制。
- 如果创建数据分片时超时,也可以通过在 fe.conf 中设置 tablet_create_timeout_second=xxx 以及 max_create_table_timeout_second=xxx 来延长超时时间。其中 tablet_create_timeout_second 默认是1秒, max_create_table_timeout_second 默认是60秒,总体的超时时间为min(tablet_create_timeout_second * replication_num, max_create_table_timeout_second);
-
建表命令长时间不返回结果。
- Doris 的建表命令是同步命令。该命令的超时时间目前设置的比较简单,即(tablet num * replication num)秒。如果创建较多的数据分片,并且其中有分片创建失败,则可能导致等待较长超时后,才会返回错误。
- 正常情况下,建表语句会在几秒或十几秒内返回。如果超过一分钟,建议直接取消掉这个操作,前往 FE 或 BE 的日志查看相关错误。