Doris:数据库建表最佳实践

目录

一、表模型推荐归约

二、字段推荐归约

三、建表推荐归约

四、建表强制归约

五、最佳实践


        Doris 数据表模型上目前分为三类:DUPLICATE KEY, UNIQUE KEY, AGGREGATE KEY。因为数据模型在建表时就已经确定,且无法修改。所以,选择一个合适的数据模型非常重要。

        建表时除了要注意数据表模型、索引和字段类型的选择还需要注意分区分桶的设置。

一、表模型推荐归约

        1. Duplicate: 适合任意维度的 Ad-hoc 查询。虽然同样无法利用预聚合的特性,但是不受聚合模型的约束,可以发挥列存模型的优势(只读取相关列,而不需要读取所有 Key 列)。

        2. Aggregate: 模型可以通过预聚合,极大地降低聚合查询时所需扫描的数据量和查询的计算量,非常适合有固定模式的报表类查询场景。但是该模型对 count(*) 查询很不友好。同时因为固定了 Value 列上的聚合方式,在进行其他类型的聚合查询时,需要考虑语意正确性。

        3. Unique: 模型针对需要唯一主键约束的场景,可以保证主键唯一性约束。但是无法利用物化等预聚合带来的查询优势。对于聚合查询有较高性能需求的用户,推荐使用自 1.2 版本加入的写时合并实现。

        4.如果有部分列更新的需求,可以选择:
        a. Unique 模型的 Merge-on-Write 模式
        b. Aggregate 模型的 REPLACE_IF_NOT_NULL 聚合方式

二、字段推荐归约

        1. VARCHAR

        a. 变长字符串,长度范围为:1-65533 字节长度,以 UTF-8 编码存储的,因此通常英文字符占 1 个字节,中文字符占 3 个字节。
        b. 这里存在一个误区,即 varchar(255) 和 varchar(65533) 的性能问题,这二者如果存的数据是一样的,性能也是一样的,建表时如果不确定这个字段最大有多长,建议直接使用 65533 即可,防止由于字符串过长导致的导入问题。

        2. STRING

        a. 变长字符串,默认支持 1048576 字节(1MB),可调大到 2147483643 字节(2G),以 UTF-8 编码存储的,因此通常英文字符占 1 个字节,中文字符占 3 个字节。
        b. 只能用在 Value 列,不能用在 Key 列和分区分桶列。
        c. 适用于一些比较大的文本存储,一般如果没有这种需求的话,建议使用 VARCHAR,STRING 列无法用在 Key 列和分桶列,局限性比较大。

        3. 数值型字段:按照精度选择对应的数据类型即可,没有过于特殊的注意。

        4. 时间字段:这里需要注意的是,如果有高精度(毫秒值时间戳)需求,需要指明使用 datetime(6),否则默认是不支持毫秒值时间戳的。

        5. 建议使用 JSON 数据类型代替字符串类型存放 JSON 数据的使用方式。

三、建表推荐归约

        1. 库名统一使用小写方式,中间用下划线(_)分割,长度 62 字节内。

        2. 表名称大小写敏感,统一使用小写方式,中间用下划线(_)分割,长度 64 字节内。

        3. 能手动分桶,尽量不要使用 Auto Bucket,按照自己的数据量来进行分区分桶,这样你的导入及查询性能都会得到很好的效果,Auto Bucket 会造成 tablet 数量过多,造成大量小文件的问题。

        4. 1000W-2 亿以内数据为了方便可以不设置分区,直接用分桶策略(不设置其实 Doris 内部会有个默认分区)。

        5. 如果是时序场景,建议在建表时 "compaction_policy" = "time_series" 加上这个表属性配置,在时序场景持续导入的情况下有效降低 compact 的写入放大率,注意需要配合倒排一起用。

四、建表强制归约

        1. 数据库字符集指定 UTF-8,并且只支持 UTF-8。

        2. 表的副本数必须为 3(未指定副本数时,默认为 3)。

        3. 单个 Tablet(Tablet 数 = 分区数 * 桶数 * 副本数)的数据量理论上没有上下界,除小表(百兆维表)外需确保在 1G - 10G 的范围内:

                a. 如果单个 Tablet 数据量过小,则数据的聚合效果不佳,且元数据管理压力大。
                b. 如果数据量过大,则不利于副本的迁移、补齐,且会增加 Schema Change 或者 物化 操作失败重试的代价(这些操作失败重试的粒度是 Tablet)。

        4. 5 亿以上的数据必须设置分区分桶策略:

        a. bucket 设置建议:

                i. 大表的单个 Tablet 存储数据大小在 1G-10G 区间,可防止过多的小文件产生。

                ii. 百兆左右的维表 Tablet 数量控制在 3-5 个,保证一定的并发数也不会产生过多的小文件。

        b. 没有办法分区的,数据又较快增长的,没办法按照时间动态分区,可以适当放大一下你的 Bucket 数量,按照你的数据保存周期(180 天)数据总量,来估算你的 Bucket 数量应该是多少,建议还是单个 Bucket 大小在 1-10G。

        c. 对分桶字段进行加盐处理,业务上查询的时候也是要同样的加盐策略,这样能利用到分桶数据剪裁能力。

        d. 数据随机分桶:

        i. 如果 OLAP 表没有更新类型的字段,将表的数据分桶模式设置为 RANDOM,则可以避免严重的数据倾斜 (数据在导入表对应的分区的时候,单次导入作业每个 Batch 的数据将随机选择一个 Tablet 进行写入)。

        ii. 当表的分桶模式被设置为 RANDOM 时,因为没有分桶列,无法根据分桶列的值仅对几个分桶查询,对表进行查询的时候将对命中分区的全部分桶同时扫描,该设置适合对表数据整体的聚合查询分析而不适合高并发的点查询。

        iii. 如果 OLAP 表的是 Random Distribution 的数据分布,那么在数据导入的时候可以设置单分片导入模式(将 `load_to_single_tablet` 设置为 true),那么在大数据量的导入的时候,一个任务在将数据写入对应的分区时将只写入一个分片,这样将能提高数据导入的并发度和吞吐量,减少数据导入和 Compaction 导致的写放大问题,保障集群的稳定性。


        e. 维度表:缓慢增长的,可以使用单分区,在分桶策略上使用常用查询条件(这个字段数据分布相对均衡)分桶。

        f. 事实表

        5. 如果分桶字段存在 30% 以上的数据倾斜,则禁止使用 Hash 分桶策略,改使用 RANDOM 分桶策略。

        6. 2KW 以内数据禁止使用动态分区(动态分区会自动创建分区,而小表用户客户关注不到,会创建出大量不使用分区分桶)。

        7. 对于有大量历史分区数据,但是历史数据比较少,或者不均衡,或者查询概率的情况,使用如下方式将数据放在特殊分区。

        对于历史数据,如果数据量比较小我们可以创建历史分区(比如年分区,月分区),将所有历史数据放到对应分区里创建历史分区方式例如:FROM ("2000-01-01") TO ("2022-01-01") INTERVAL 1 YEAR,具体参考:


    PARTITION p00010101_1899 VALUES [('0001-01-01'), ('1900-01-01')),    
    PARTITION p19000101 VALUES [('1900-01-01'), ('1900-01-02')),    
    ...    
    PARTITION p19000104_1999 VALUES [('1900-01-04'), ('2000-01-01')),
    FROM ("2000-01-01") TO ("2022-01-01") INTERVAL 1 YEAR, 
    PARTITION p30001231 VALUES [('3000-12-31'), ('3001-01-01')), 
    PARTITION p99991231 VALUES [('9999-12-31'), (MAXVALUE)) 
 )

        8.单表物化视图不能超过 6 个

        a. 单表物化视图是实时构建

        b. 在 Unqiue 模型上物化视图只能起到 Key 重新排序的作用,不能做数据的聚合,因为 Unqiue 模型的聚合模型是 Replace

五、最佳实践

-- 以 Unique 模型的 Merge-on-Write 表为例
-- Unique 模型的写时合并实现,与聚合模型就是完全不同的两种模型了,查询性能更接近于 duplicate 模型,
-- 在有主键约束需求的场景上相比聚合模型有较大的查询性能优势,尤其是在聚合查询以及需要用索引过滤大量数据的查询中。-- 非分区表
CREATE TABLE IF NOT EXISTS tbl_unique_merge_on_write
(`user_id` LARGEINT NOT NULL COMMENT "用户id",`username` VARCHAR(50) NOT NULL COMMENT "用户昵称",`register_time` DATE COMMENT "用户注册时间",`city` VARCHAR(20) COMMENT "用户所在城市",`age` SMALLINT COMMENT "用户年龄",`sex` TINYINT COMMENT "用户性别",`phone` LARGEINT COMMENT "用户电话",`address` VARCHAR(500) COMMENT "用户地址"
)
UNIQUE KEY(`user_id`, `username`)
-- 3-5G 的数据量
DISTRIBUTED BY HASH(`user_id`) BUCKETS 10 
PROPERTIES (
-- 在 1.2.0 版本中,作为一个新的 feature,写时合并默认关闭,用户可以通过添加下面的 property 来开启
"enable_unique_key_merge_on_write" = "true" 
);-- 分区表
CREATE TABLE IF NOT EXISTS tbl_unique_merge_on_write_p
(`user_id` LARGEINT NOT NULL COMMENT "用户id",`username` VARCHAR(50) NOT NULL COMMENT "用户昵称",`register_time` DATE COMMENT "用户注册时间",`city` VARCHAR(20) COMMENT "用户所在城市",`age` SMALLINT COMMENT "用户年龄",`sex` TINYINT COMMENT "用户性别",`phone` LARGEINT COMMENT "用户电话",`address` VARCHAR(500) COMMENT "用户地址"
)
UNIQUE KEY(`user_id`, `username`, `register_time`)
PARTITION BY RANGE(`register_time`) (PARTITION p00010101_1899 VALUES [('0001-01-01'), ('1900-01-01')), PARTITION p19000101 VALUES [('1900-01-01'), ('1900-01-02')), PARTITION p19000102 VALUES [('1900-01-02'), ('1900-01-03')),PARTITION p19000103 VALUES [('1900-01-03'), ('1900-01-04')),PARTITION p19000104_1999 VALUES [('1900-01-04'), ('2000-01-01')),FROM ("2000-01-01") TO ("2022-01-01") INTERVAL 1 YEAR, PARTITION p30001231 VALUES [('3000-12-31'), ('3001-01-01')), PARTITION p99991231 VALUES [('9999-12-31'), (MAXVALUE)) 
) 
-- 默认 3-5G 的数据量
DISTRIBUTED BY HASH(`user_id`) BUCKETS 10 
PROPERTIES ( 
-- 在 1.2.0 版本中,作为一个新的 feature,写时合并默认关闭,用户可以通过添加下面的 property 来开启
"enable_unique_key_merge_on_write" = "true", 
-- 动态分区调度的单位。可指定为 HOUR、DAY、WEEK、MONTH、YEAR。分别表示按小时、按天、按星期、按月、按年进行分区创建或删除。
"dynamic_partition.time_unit" = "MONTH",
-- 动态分区的起始偏移,为负数。根据 time_unit 属性的不同,以当天(星期/月)为基准,分区范围在此偏移之前的分区将会被删除(TTL)。如果不填写,则默认为 -2147483648,即不删除历史分区。
"dynamic_partition.start" = "-3000",
-- 动态分区的结束偏移,为正数。根据 time_unit 属性的不同,以当天(星期/月)为基准,提前创建对应范围的分区。
"dynamic_partition.end" = "10",
-- 动态创建的分区名前缀(必选)。
"dynamic_partition.prefix" = "p",
-- 动态创建的分区所对应的分桶数量。
"dynamic_partition.buckets" = "10", 
"dynamic_partition.enable" = "true", 
-- 动态创建的分区所对应的副本数量,如果不填写,则默认为该表创建时指定的副本数量 3。
"dynamic_partition.replication_num" = "3",
"replication_num" = "3"
);  -- 分区创建查看
-- 实际创建的分区数需要结合 dynamic_partition.start、end 以及 PARTITION BY RANGE 的设置共同决定
show partitions from tbl_unique_merge_on_write_p;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145217.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

web基础—dvwa靶场(十一)CSP Bypass

CSP Bypass(CSP 绕过) 内容安全策略(CSP)用于定义脚本和其他资源可以从何处加载或执行,本模块将指导您根据开发人员犯下的常见错误来绕过该策略。 这些漏洞都不是 CSP 中的实际漏洞,它们都是实现 CSP 的方式中的漏洞。 绕过内容安…

JAVA——IO_缓冲流

目录 一、字节缓冲流 二、字符缓冲流 字符缓冲输入流( BufferedReader ) 字符缓冲输出流( BufferedWriter ) 缓冲流作用:对原始流进行包装,以提高原始流读写数据的性能 一、字节缓冲流 1. 作用:提高字节流读写数据的性能 2…

使用scp命令从本地往服务器传输文件失败

解决办法: 找到这个文件,打开,将里面的服务器ip对应的一行数据删掉即可。

【Python报错已解决】To update, run: python.exe -m pip install --upgrade pip

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

麒麟操作系统快捷键设置

这些是银河麒麟操作系统常用的快捷键,和Windows系统有点儿相似。 但也有一些快捷键为未列出来,如CtrlALTT打开终端,Ctrld关闭终端,F2:重命名; CtrlshiftN:新建文件夹。

虚拟机ens33网卡不显示inet地址(已设置NOBOOT为yes)

在虚拟机中输入ifconfig或ip addr时,出现如下情况: sudo dhclient ens33sudo ifconfig ens33依次执行上面两行,之后发现ens33中可以显示inet了 本虚拟机的地址就是192.168.244.131

ABAP 一步一步教你添加ALV界面菜单功能按钮

ABAP 一步一步教你添加菜单功能按钮。 程序里面找到这个组件小按钮 就可以看到GUI状态了。 在修改GUI STATUS 是如果要添加一个功能按钮,必须先创建一个功能键(具体参照下方),之后再在应用程序工具栏输入该功能键的功能码否则报…

Windows上创建批处理.bat文件并且注册为开机自启(Python-web微服务)

1. winodws桌面点击创建文本文件 (文件名称.txt) 2. 将如下代码写入txt文件中 echo off if "%1""h" goto begin start mshta vbscript:createobject("wscript.shell").run("""%~nx0"" h"…

百元学生党头戴式耳机选哪个?四款热门天花板机型推荐

当前市场上,耳机产品的竞争愈发激烈,降噪技术也日益精进。回想过去,要想享受到优质的降噪体验,动辄需要花费数千元,但现在,高品质的降噪耳机已经降至百元级别。在众多降噪耳机中,头戴式耳机尤为…

网站SEO,该如何规范目标网站URL配置!

随着互联网技术的飞速发展,搜索引擎优化(SEO)在网站建设和运营中的重要性日益凸显。优化目标网站的URL配置,作为SEO策略中的关键环节,对于提升网站在搜索引擎中的排名和曝光度具有至关重要的作用。大连蝙蝠侠科技将从U…

掌握IT资产发现的三个步骤

IT 资产生态系统非常复杂,因为资产不断变化,包括新增资产、移除过时资产或修改现有资产。在这种动态环境中,IT 资产管理者很难全面查看所有拥有的资产。 根据Gartner的预测,到 2025 年,大约 30% 的关键基础设施组织将…

Hutool树结构工具-TreeUtil构建树形结构

1 pom.xml <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version> </dependency> 2 核心代码 import cn.beijing.satoken.domain.ZhiweiCityArea; import cn.beijing.sa…

机器人上的DPDK使用思考

引言 项目背景 人形机器人作为智能技术的集大成者&#xff0c;正逐步从科幻电影走进现实生活&#xff0c;广泛应用于工业制造、医疗健康、家庭服务等多个领域。在这一发展过程中&#xff0c;传感器技术的飞速发展和物联网技术的广泛应用&#xff0c;极大地提升了人形机器人对…

【AI视频】Runway:Gen-2 运镜详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI视频 | Runway 文章目录 &#x1f4af;前言&#x1f4af;Camera Control&#xff08;运镜&#xff09;&#x1f4af;Camera Control功能测试Horizonta&#xff08;左右平移&#xff09;Vertical&#xff08;上下平移&#xff0…

双token无感刷新

文章目录 &#x1f7e2;双token无感刷新1、token过期续期的五种方案对比2、双token的基本概念3、双token无感刷新的原理4、双token无感刷新的实现方式5.前端实现 ✒️总结 &#x1f7e2;双token无感刷新 对于token无感刷新这个东西有复杂度的话&#xff0c;它主要在后端&#x…

【使用Hey对vllm接口压测】模型并发能力

使用Hey对vllm进行模型并发压测 docker run --rm --networkknowledge_network \registry.cn-shanghai.aliyuncs.com/zhph-server/hey:latest \-n 200 -c 200 -m POST -H "Content-Type: application/json" \-H "Authorization: xxx" \-d {"model"…

如何查询论文的SCI检索号?

一、登录Web of Science 不要自己登录&#xff0c;需要选择机构为CHINA CERNET Federation&#xff0c;否则无法查询文章。 然后转到机构&#xff0c;选择对应的大学。 更具对应文章名查询文献。 二、查询文献名

CUDA并行架构

一、CUDA简介 CUDA(Compute Unified Device Architecture)是一种由NVIDIA推出的通用并行计算架构&#xff0c;该架构使GPU(Graphics Processing Unit)能够对复杂的计算问题做性能速度优化。 二、串并行模式 高性能计算的关键是利用多核处理器进行并行计算。 串行模式&#…

使用Anaconda安装pyTorch

1.Anaconda简介 Anaconda 是一个流行的 Python 数据科学和机器学习平台&#xff0c;它简化了包管理和部署&#xff0c;使得安装、运行和升级包及其依赖变得非常容易。Anaconda 通过其内置的 Conda 包和环境管理器&#xff0c;提供了一个强大的环境&#xff0c;用于科学计算&…

鸿蒙手势交互(四:多层手势)

四、多层手势 指父子组件嵌套时&#xff0c;父子组件均绑定了手势或事件。有两种&#xff0c;一种默认多层级手势事件&#xff0c;一种自定义多层级手势事件。 默认多层级手势事件&#xff1a;需要分清两个概念&#xff0c;触摸事件&#xff0c;手势与事件 触摸事件&#xf…