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
是的
可以