目前随着doris的使用范围越来越广,那么对于初次接触到doris的用户来说,我们建议提前熟悉下相关的规范,这样可以避免后续出现各种问题。本文的话,我们从三个方面来介绍下doris的使用规范:
1、字符集规范 2、建表规范 3、数据变更规范 4、数据查询规范
下面我们挨个来介绍下:
一、字符集规范
【强制】数据库字符集指定utf-8,并且只⽀持utf-8。
命令规范
1. 【建议】库名统⼀使⽤⼩写⽅式,中间⽤下划线(_)分割,⻓度62字节内
2. 【建议】表名称⼤⼩写敏感,统⼀使⽤⼩写⽅式,中间⽤下划线(_)分割,⻓度64字节内
二、建表规范
1、【强制】确保每个tablet⼤⼩为1-3G之间。举例:假设表内单分区数据量在100G,按天分区,bucket数量100个。
2、【强制】 5 亿以上的数据必须设置分区分桶策略
a. 维度表:缓慢增⻓的,可以使⽤单分区,在分桶策略上使⽤常⽤查询条件(这个字段数据分步相对均衡)分桶, i. 100M以内:1 buckets ii. 100M-1G :3-5 个 Buckets iii. ⼤于1G-3G : 5-7个 buckets iv. 3-5G : 7-10 个 buckets
b. 事实表 i. 没有办法分区的,数据⼜缓慢增⻓的:单个tablet数据量保持在1-3G;⽐如5亿数据⼤⼩在20G,bucket数量给20个 ii. 没有办法分区的,数据⼜较快增⻓的,没办法按照时间动态分区,可以适当放⼤⼀下你的bucket数量,按照你的数据保存周期(180天)数据总量,来估算你的bucket数量应该是多少,建议还是单个bucket⼤⼩在1-3G。
避免数据倾斜的问题 a. ⼀个是对分桶字段进⾏加盐处理,业务上查询的时候也是要同样的加盐策略,这样能利⽤到分桶数据剪裁能⼒ b. 另外⼀个是数据随机分桶,这种缺点是没办法利⽤数据分桶剪裁能⼒,数据分布会很均匀
3、【建议】 1000w-2 亿以内数据为了⽅便可以不设置分区,直接⽤分桶策略。(不设置其实Doris内 部会有个默认分区)
4、【强制】 2000kw 以内数据禁⽌使⽤动态分区(动态分区会⾃动创建分区,⽽⼩表⽤⼾客⼾关注不 到,会创建出⼤量不使⽤分区分桶)
5、【强制】对于有⼤量历史分区数据,但是历史数据⽐较少,或者不均衡,或者查询概率的情况,使 ⽤如下⽅式将数据放在特殊分区。
对于历史数据,如果数据量⽐较⼩我们可以创建历史分区(⽐如年分区,⽉分区),将所有历史数据放到对应分区⾥
6、【强制】如果分桶字段存在30%以上的数据倾斜,则禁⽌使⽤Hash分桶策略,改使⽤random分桶 策略
7、前缀索引的第⼀个字段⼀定是最⻓查询的字段,并且需要是⾼基字段。这⾥⾯选取分区分 桶外最⻓查询且⾼基数的列
前缀索引(36位):第⼀个字段查询性能最好,前缀索引碰⻅varchar类型的字段,会⾃动截断前20个字符 i. Int(4)+ Int(4) + varchar(50),前缀索引⻓度只有28 ii. Int(4) + varchar(50) + Int(4),前缀索引⻓度只有24 iii. varchar(10) + varchar(50) ,前缀索引⻓度只有30 最常⽤的查询字段如果能放到前缀索引⾥尽可能放到前注意⼒,如果不能,可以放到分桶字段⾥ 分桶字段注意事项:这个⼀般是数据分布⽐较均衡的,也是经常使⽤的字段,最好是⾼基数字段 good case :UNIQUE KEY( user_id , age ) user_id最⻓被查询,且数据分布⽐较散 bad case :UNIQUE KEY( age , user_id ) age是低基数列,且可能存在数据倾斜
8、【强制】表的副本数必须为3
9、【建议】前缀索引中的字段⻓度尽可能明确,因为Doris只有前36个字节能⾛前缀索引
10、【强制】除了UNIQUE KEY和aggregate key要构建key的情况,否则不要基数(例如user_type) ⼩于50的字段建⽴任何索引。因为Doris内置了字典类型优化。
a、已经有了低基数优化了 b. Unique Key 是aggregate key 的⼀个特例,当aggregate key 的key 保持唯⼀其实就是Unqiue key 模型
11、【强制】BloomFilter索引必须在查询条件是in或者=,并且是⾼基(5000以上)列上构建。
a. 数据基数在⼀半左右 b. 类似⾝份证号这种基数特别⾼并且查询是等值(=)查询,使⽤Bitmap索引能极⼤加速 c. Bloomfilter 使⽤场景: i. ⾸先BloomFilter适⽤于⾮前缀过滤。 ii. 查询会根据该列⾼频过滤,⽽且查询条件⼤多是 in 和 = 过滤。 iii. 不同于Bitmap, BloomFilter适⽤于⾼基数列。⽐如UserID。因为如果创建在低基数的列上,⽐如 “性别” 列,则每个Block⼏乎都会包含所有取值,导致BloomFilter索引失去意义。
12、【强制】bitmap索引必须在⼀定基数范围内构建,太⾼或者太低的基数都不合适
a. 这种索引更多的适合正交查询 b. 适⽤场景: 适⽤于低基数的列上,建议在100到100,000之间,如:职业、地市等。 重复度过⾼则对⽐其他类型索引没有明显优势;重复度过低,则空间效率和性能会⼤⼤降低。 特定类型的查询例如count、or、and 等逻辑操作因为只需要进⾏位运算 c. Bitmap 索引⽀持类型: ▪ bitmap 索引⽀持的数据类型如下: • TINYINT • SMALLINT • INT • BIGINT • CHAR • VARCHAR • DATE • DATETIME • LARGEINT • DECIMAL • BOOL
13、【强制】亿级别以上数据,如果有模糊匹配,使⽤倒排索引或者是 NGram Bloomfilter
14、【建议】如果某个范围数据在分区分桶和前缀索引中都不好设计,可以考虑引⼊倒排索引加速。
15、【强制】单表物化视图不能超过6个
a. 单笔物化视图是实时构建 b. 在unique 模型上物化视图只能起到 Key 重新排序的作⽤,不能做数据的聚合,因为Unqiue模型的聚合模型是replace
16、【建议】建议使⽤JSON数据类型代替字符串类型存放JSON数据的使⽤⽅式
三、数据变更规范
1、【强制】应⽤程序不可以直接使⽤delete后者update语句变更数据,使⽤CDC的upsert⽅式来实现。
a. 低频操作上使⽤,⽐如 Update ⼏分钟更新⼀次 b. 如果使⽤ Delete ⼀定带上分区条件
2、【强制】DBA执⾏delete后者update语句时必须带分区条件
3、【强制】禁⽌使⽤INSERT INTO tbl1 VALUES ("1"), (
4、【建议】特殊⼤的ETL操作,简单单独在Session中设置超时时间
a、SELECT /*+ SET_VAR(query_timeout = 1*/ sleep(3); 类似这样通过Hint⽅式去设置Session 会话变量,不要设置全局的系统变量
四、数据查询规范
1、【强制】in 中条件超过 2000 后,必须修改为⼦查询
2、【强制】禁⽌使⽤REST API(Statement Execution Action)知道⼤量SQL查询,改接⼝仅仅⽤于 集群维护。
3、【建议】⼀次insert into select 数据超过1亿条后,建议拆分为多个insert into select语句执⾏,分成多个批次来执⾏。
如果真的是要这样执⾏,在集群资源相对空闲的时候可以通过调整并发度来加快的数据导⼊速度 set parallel_fragment_exec_instance_num = 8 或者 16 建议是你CPU内核的⼀半 insert into new_tbl select * from old_tbl
4、【强制】query查询条件返回结果在5w条以上,使⽤JDBC Catalog或者OUTFILE⽅式导出。不然 ⼤量FE上数据传输将占⽤FE资源,影响集群稳定性
a、如果你是交互式查询,建议使⽤分⻚⽅式(offset limit),分⻚要加Order by b. 如果是数据导出提供给第三⽅使⽤,建议使⽤ outfile 或者 export ⽅式
5、【建议】query查询如果有⼤量的数据传输需求,建议部署observer节点并在该该节点执⾏查询 (私有化部署)
建议的⽅式是 1 FE(Follower) + 多个 OBserver(FE)⽅式,读写分析,所有的写连接Follower,所有的读连接Observer
6、【建议】尽量不要使⽤OR 作为 JOIN条件
7、【建议】⼤量数据排序(5亿以上)后返回部分数据,建议先减少数据范围在执⾏排序,否则⼤量 排序会影响性能。
select /*+ set_var(parallel_fragment_exec_instance_num=8) */ krr.sequence_id , krr.event_occur_time_date , krr.event_occur_time , krr.partner_code , krr.app_name , krr.event_id , krr.event_type , krr.success , krr.final_decision , krr.final_score, krr.account_login , krr.account_mobile , krr.dev_success , krr.policy_name , krr.policy_version , krr.sub_reason_codes , krr.policy_uuid , krr.reason_code , krr.score , krr.event_real_time , krr.produce_time , krr.account_email from kunpeng_risk_record krr where krr.event_occur_time_date between '2023-10-01 00:00:00' and '2023-10-25 23:59:59' and krr.partner_code = 'liveme' order by krr.sequence_id desc limit 20;
例如将 from table order by datatime desc limit 10 优化为from table where datatime='2023-10-20' order by datatime desc limit 10
8、【强制】2个以上⼤于3亿的表 JOIN 使⽤ Colocate JOIN
9、【强制】亿级别⼤表禁⽌使⽤select * 查询,查询时需要明确要查询的字段
a、SQL Block⽅式禁⽌这种操作 b、如果是⾼并发点查,建议开启⾏存
表属性级别 "enable_unique_key_merge_on_write" = "true", "store_row_column" = "true" be.conf disable_storage_row_cache 是否开启⾏缓存, 默认不开启 使⽤PrepareStatement模板
10、【强制】亿级以上表数据查询必须带分区分桶条件
还没有评论,来说两句吧...