doris tips

1 schema表格式字段长度

如果是数字+字母这种的长度等于hive sql里面  length(variable)的长度

如果是中文要占3-4个Char

2 表增加分区
可以通过脚本自己构造多个sql 语句
类似
ALTER TABLE example_db.my_table ADD PARTITION p20140102 VALUES [("20140101"), ("20140102"));

3 应用场景

Doris 场景

目前明确可支持的场景

  • 聚合查询场景

    • 查询模式通常为select sum/max/min/count from group by

    • 数据特征一般为上游原始数据在Doris中聚合后数据量会数据量级的减少,利用Doris的聚合模型收益很高

    • 可以利用Rollup进一步提升聚合度

  • 明细查询场景

    • 可以利用Doris的前缀索引或者bitmap索引实现点查或者小范围scan

    • 可以使用物化视图进行聚合查询,比Rollup更加灵活

  • 灵活的多维过滤场景

    • 支持前缀索引进行谓词过滤,使用Rollup/物化索引可以灵活定制前缀索引

    • 支持bitmap索引作为二级过滤

  • 从Hive以离线的方式T+1/灵活日期导入,自动编码bitmap字典,支持最多TB级别数据导入

  • 从Kafka实时导入,参考峰值TPS在5w左右,和模型设计相关,具体上限需要实测。实时性目前弱于Druid

  • 查询延迟 TP99 3~5s

  • 查询QPS 单集群100以下

暂时无法支持的场景

  • 数据导出Doris到其他存储介质,比如ToMySQL,ToHive(Coming soon);大结果集(百万行)的导出性能很差

  • 目前不支持除了Hive和Kafka之外其他数据源的导入

  • 单次上游TB级别的数据导入,难以满足用户对于延时的要求

  • 高QPS场景,比如单集群上万QPS;稳定的亚秒级(几百毫秒)响应

  • 稳定性和可用性无法和MySQL相比,因此目前Doris的主要发力方向还是面向公司内部的分析场景;支持在线业务能力较弱,稳定性难以保障

  • 异步长查询(20s以上,分钟级查询),建议使用Presto等Ad-hoc引擎

  • 不支持需要Scan大量数据(几十GB)同时进行复杂计算(大数据量shuffle)的查询,未来可能通过SparkOnDoris解决

  • 支持低频点更新/点删除,高频点更新对查询性能影响很大

  • Doris只能通过Replace聚合模型通过导入批量数据实现对相同key的value列的更新,但是导入同一批次对于相同key有多个value列,更新顺序无法保证

  • 基于任意时间窗口的聚合操作

一定不支持的场景

  • OLTP场景,类似MySQL一样的增删改查

4 shuffle知识点

4.1  Broadcast/Shuffle Join
系统默认实现 Join 的方式,是将小表进行条件过滤后,将其广播到大表所在的各个节点上,形成一个内存 Hash 表,然后流式读出大表的数据进行Hash Join。但是如果当小表过滤后的数据量无法放入内存的话,此时 Join 将无法完成,通常的报错应该是首先造成内存超限。

如果遇到上述情况,建议显式指定 Shuffle Join,也被称作 Partitioned Join。即将小表和大表都按照 Join 的 key 进行 Hash,然后进行分布式的 Join。这个对内存的消耗就会分摊到集群的所有计算节点上。

Doris会自动尝试进行 Broadcast Join,如果预估小表过大则会自动切换至 Shuffle Join。注意,如果此时显式指定了 Broadcast Join 也会自动切换至 Shuffle Join。

使用 Broadcast Join(默认):
 

mysql> select sum(table1.pv) from table1 join table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.20 sec)

使用 Broadcast Join(显式指定):

mysql> select sum(table1.pv) from table1 join [broadcast] table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.20 sec)

使用 Shuffle Join:

mysql> select sum(table1.pv) from table1 join [shuffle] table2 where table1.siteid = 2;
+--------------------+
| sum(`table1`.`pv`) |
+--------------------+
|                 10 |
+--------------------+
1 row in set (0.15 sec)

4.2 Colocation Join

4.3.1 名词解释

FE:Frontend,Doris 的前端节点。负责元数据管理和请求接入。

BE:Backend,Doris 的后端节点。负责查询执行和数据存储。

Colocation Group(CG):一个 CG 中会包含一张及以上的 Table。在同一个 Group 内的 Table 有着相同的 Colocation Group Schema,并且有着相同的数据分片分布。

Colocation Group Schema(CGS):用于描述一个 CG 中的 Table,和 Colocation 相关的通用 Schema 信息。包括分桶列类型,分桶数以及副本数等。

4.3.2 原理

doris 除了支持Broadcast/Shuffle Join 之外,Colocation Join更是一大特色。 Colocation Join 功能,是将一组拥有相同 CGS 的 Table 组成一个 CG。并保证这些 Table 对应的数据分片会落在同一个 BE 节点上。使得当 CG 内的表进行分桶列上的 Join 操作时,可以通过直接进行本地数据 Join,减少数据在节点间的传输耗时。

为了使得 Table 能够有相同的数据分布,同一 CG 内的 Table 必须保证以下属性相同:

分桶列和分桶数

分桶列,即在建表语句中 DISTRIBUTED BY HASH(col1, col2, ...) 中指定的列。分桶列决定了一张表的数据通过哪些列的值进行 Hash 划分到不同的 Tablet 中。同一 CG 内的 Table 必须保证分桶列的类型和数量完全一致,并且桶数一致,才能保证多张表的数据分片能够一一对应的进行分布控制。

副本数

同一个 CG 内所有表的所有分区(Partition)的副本数必须一致。如果不一致,可能出现某一个 Tablet 的某一个副本,在同一个 BE 上没有其他的表分片的副本对应。

同一个 CG 内的表,分区的个数、范围以及分区列的类型不要求一致。

CREATE TABLE `tbl1` (
    `k1` date NOT NULL COMMENT "",
    `k2` int(11) NOT NULL COMMENT "",
    `v1` int(11) SUM NOT NULL COMMENT ""
) ENGINE=OLAP
AGGREGATE KEY(`k1`, `k2`)
PARTITION BY RANGE(`k1`)
(
    PARTITION p1 VALUES LESS THAN ('2019-05-31'),
    PARTITION p2 VALUES LESS THAN ('2019-06-30')
)
DISTRIBUTED BY HASH(`k2`) BUCKETS 8
PROPERTIES (
    "colocate_with" = "group1"
);
CREATE TABLE `tbl2` (
    `k1` datetime NOT NULL COMMENT "",
    `k2` int(11) NOT NULL COMMENT "",
    `v1` double SUM NOT NULL COMMENT ""
) ENGINE=OLAP
AGGREGATE KEY(`k1`, `k2`)
DISTRIBUTED BY HASH(`k2`) BUCKETS 8
PROPERTIES (
    "colocate_with" = "group1"
);

查看查询计划,如果 Colocation Join 生效,则 Hash Join 节点会显示 colocate: true

DESC SELECT * FROM tbl1 INNER JOIN tbl2 ON (tbl1.k2 = tbl2.k2);
+----------------------------------------------------+
| Explain String                                     |
+----------------------------------------------------+
| PLAN FRAGMENT 0                                    |
|  OUTPUT EXPRS:`tbl1`.`k1` |                        |
|   PARTITION: RANDOM                                |
|                                                    |
|   RESULT SINK                                      |
|                                                    |
|   2:HASH JOIN                                      |
|   |  join op: INNER JOIN                           |
|   |  hash predicates:                              |
|   |  colocate: true                                |
|   |    `tbl1`.`k2` = `tbl2`.`k2`                   |
|   |  tuple ids: 0 1                                |
|   |                                                |
|   |----1:OlapScanNode                              |
|   |       TABLE: tbl2                              |
|   |       PREAGGREGATION: OFF. Reason: null        |
|   |       partitions=0/1                           |
|   |       rollup: null                             |
|   |       buckets=0/0                              |
|   |       cardinality=-1                           |
|   |       avgRowSize=0.0                           |
|   |       numNodes=0                               |
|   |       tuple ids: 1                             |
|   |                                                |
|   0:OlapScanNode                                   |
|      TABLE: tbl1                                   |
|      PREAGGREGATION: OFF. Reason: No AggregateInfo |
|      partitions=0/2                                |
|      rollup: null                                  |
|      buckets=0/0                                   |
|      cardinality=-1                                |
|      avgRowSize=0.0                                |
|      numNodes=0                                    |
|      tuple ids: 0                                  |
+----------------------------------------------------+
 

支持Bitmap

使用 Roaring Bitmap 数据结构,现场查询时的 IO,CPU,内存,网络资源会显著减少,并且不会随着数据规模线性增加。

CREATE TABLE `pv_bitmap` (
`dt` int,
`page` varchar(10),
`user_id` bitmap bitmap_union
)
AGGREGATE KEY(`dt`, page)
DISTRIBUTED BY HASH(`dt`) BUCKETS 2;
select bitmap_count(bitmap_union(user_id)) from pv_bitmap; 
select bitmap_union_count(user_id) from pv_bitmap;
select bitmap_union_int(id) from pv_bitmap; 
BITMAP_UNION(expr) : 计算两个 Bitmap 的并集,返回值是序列化后的 Bitmap 值 
BITMAP_COUNT(expr) : 计算 Bitmap 的基数值 
BITMAP_UNION_COUNT(expr): 和 BITMAP_COUNT(BITMAP_UNION(expr)) 等价 
BITMAP_UNION_INT(expr) : 和 COUNT(DISTINCT expr) 等价 (仅支持 TINYINT,SMALLINT 和 INT)

4.6 物化视图
物化视图是将预先计算(根据定义好的 SELECT 语句)好的数据集,存储在 Doris 中的一个特殊的表。

物化视图的出现主要是为了满足用户,既能对原始明细数据的任意维度分析,也能快速的对固定维度进行分析查询。

在没有物化视图功能之前,用户一般都是使用 Rollup 功能通过预聚合方式提升查询效率的。但是 Rollup 具有一定的局限性,他不能基于明细模型做预聚合。

物化视图则在覆盖了 Rollup 的功能的同时,还能支持更丰富的聚合函数。所以物化视图其实是 Rollup 的一个超集。

也就是说,之前 ALTER TABLE ADD ROLLUP 语法支持的功能现在均可以通过 CREATE MATERIALIZED VIEW 实现。

create materialized view store_amt as
select store_id, sum(sale_amt) from sales_records group by store_id;

物化视图具体链接
四、Doris物化视图 - 天戈朱 - 博客园

5 重要技巧

a 

帮忙看下这个问题吧

b
内存超了

b
用shuffle join可以解决

我需要设置一下吗
16:07



不是默认的吗

@b 

b
你这个走了broadcast join

b
默认

b
你需要加个shuffle的hint

有wiki 吗
16:23

@b   

b
doris官方文档

b
搜shuffle就搜到了

我看看
20:42

select t1.*,
       t2.*
  from (
        select *
          from merchant.app_aggr_poi_fxb
         where partition_date = '2021-12-13'
      limit 100
       ) t1
   join [shuffle] (
        select *
          from merchant.app_aggr_brand_fxb
         where partition_date = '2021-12-13'
       ) t2
    on t1.brand_id = t2.brand_id
 limit 200



改成shuffle join 之后报超时

b
这回不是超内存,而是超时了

b
那你用presto查吧

这样的数据量 join   doris支持不了吗

这个数据量不大啊

b
不是支持不了,而是默认的2G限制跑不过

1条回复

我们在设计应用层数据

b
魔数不支持修改doris的内存限制

b:不是支持不了,而是默认的2G限制跑不过
后端接口可以修改吗

b
可以

这个2G具体是哪个指标

b
就是内存限制

配置字段发我下  我谷歌下

[抱拳]

b
exec_mem_limit

doris 查询内存2G 不够吗?  可以多往几个节点,增加并行度不可以吗?

b
那也可以

可以为什么查不出来呢  我还可以配置下参数?

b
不理解你为什么不理解查不出来

b
机器数固定就那些,数据量就固定那些,那一个节点处理的数据也就固定超过2G

shuffle join 的话,我能不能加点并发查出来啊?

b
一个sql的实例数是由分桶数确定的

1条回复

意思是我们这个集群  在2G内存限制下,机器数量不够了

b
可以这么理解

b
或者你的分桶数没达到集群的机器数

b:一个sql的实例数是由分桶数确定的
限制并行度的不仅仅是我们这个集群,还有分桶数量?

b
你分桶遍布在集群所有机器上,才能利用整个集群的机器

b
就遍布在两三台机器,就只能用这两三台机器的资源

分桶是存储,运算的时候不能多往几台机器上分配下数据吗

b
计算的机器数不能大于存储的机器数

b
数据存在哪,你就只能用哪的机器来算

b
不能动态增加额外的机器

1条回复

table a join  table b 
计算的机器是取决于哪个表的分桶数量啊?

b
a union b

b
A存在1、2、3机器
B存在3、4、5机器
那join可能用到1、2、3、4、5

b:不能动态增加额外的机器
这是doris 本身引擎规定的对吧?
但是我当时分桶的时候估计了一个分桶1G数据量。。

b
是规定的

但是我当时分桶的时候估计了一个分桶1G数据量。。

1条回复

select t1.*,
       t2.*
  from (
        select iph_poi_id, poi_name, city_name,brand_id
          from merchant.app_aggr_poi_fxb
         where partition_date = '2021-12-13'
      limit 100
       ) t1
   join [shuffle] (
        select brand_id
          from merchant.app_aggr_brand_fxb
         where partition_date = '2021-12-13'
       ) t2
    on t1.brand_id = t2.brand_id
 limit 200

我裁剪了下字段可以了  

b
[强]



b
那估计你用broadcast也可以

但是我当时分桶的时候估计了一个分桶1G数据量。。
还要考虑倾斜对吧

b
是的

可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值