哔哩哔哩在湖仓一体查询加速上的实践与探索
如果无法正常显示,请先停止浏览器的去广告插件。
1. 哔哩哔哩在湖仓一体
查询加速上的实践探
索
李呈祥 技术专家
2. About Me
• 10多年的分布式系统和开源大数据
框架开发经验,Apache Hive/Flink
Committer。
• 曾在Intel/唯品会/阿里云等负责
Hive/Flink/Spark等开源组件的研发工
作和大数据平台的建设。
• 目前在哔哩哔哩负责OLAP平台的建
设,支持公司内部业务交互式分析
的需求。
• 我的技术专栏:
https://www.zhihu.com/column/hado
op
分享嘉宾:李呈祥
3. 目录 CONTENT
01 什么是湖仓一体
02 湖仓一体架构
03 数据的排序组织
04 索引的增强
Global Order/ZOrder
BloomFilter/BitMap
4. 01
什么是湖仓一
体
5. 什么是数据湖?
• 统一的存储系统,没有数据孤岛
• 任意数据类型:结构化/半结构化/非结构化
• 对多个计算引擎开放,有限的执行效率优化
• 灵活的数据处理接口:SQL/DataSet/ML/File
等
• 较低的数据质量,难管理。
灵活,易用,适
合基于未知数据
的探索和创新
6. 什么是数据仓库?
• 强格式,事前建模
• 封闭的数据格式与存储,不对其他引擎开放
• 查询效率高:存储计算的紧密结合优化,丰
富的索引/预计算等支持
• 数据入仓->数据的存储组织由数仓而非写入
任务决定
• 数据质量高,容易运维管理,建设成本高
高效,可靠,适
合基于已知数据
的分析与决策
7. 数据湖和数据仓库的Gap
SQL on Hadoop
分布式数仓
8. 湖仓一体的目标
像湖一样灵活
像仓一样高效
像风一样自由
(智能化)
•
•
统一的HDFS存储
和SQL on Hadoop生态系统无
缝兼容。
–
– Spark/Flink ETL数据接入
SQL/ML/DataSet等各层次API访问
– Presto/Spark/Hive等多引擎
•
•
•
查询效率:
–
– 数据分布组织
索引
– 预计算
– 计算存储一体优化/缓存等
实时数仓
粗粒度事务
•
•
•
小文件过多?
数据怎么排序?
提前预计算?
• 常用过滤字段?
• 常用聚合维度和统
计项?
• 我有一个表
大数据专
家
自动化
智能化
9. 02
湖仓一体架构
10. 哔哩哔哩的湖仓一体架构
• 数据接入:Spark(离线),
Flink(实时)
• 数据优化:Magnus
• 数据缓存:Alluxio
• 查询引擎:Trino
11. Magnus:Iceberg数据管理服务
• 基本信息展示:
• 表/分区/文件
• Snapshot
• Scheduler:数据优化作业
调度
• 作业管理
12. 开源的湖仓一体方案与分布式数仓的性能Gap
Runtime引擎 存储 预计算
CodeGen 存储格式 物化视图
向量化 排序组织 Cube
RBO/CBO 索引
13. 03
数据的排序组
织
14. 典型的多维分析场景
Star Schema Benchmark
https://www.cs.umb.edu/~poneil/StarSchemaB.pdf
15. 典型的多维分析场景
关联
过滤
过滤条件:
1. 等值过滤: =, IN等
2. 范围过滤: >, >=, <, <=, BETWEEN AND等
聚合
排序
过滤字段:
1. 高基数字段
2. 低基数字段
16. 典型的多维分析场景
如何在各种类型字段及各种过滤条件下,执行
查询时只读取需要的数据?
数据组织
索引
17. 索引:MinMax索引
Age OBD Name Age OBD Name File Field Min Max
16 1 Alice 17 3 Eric File1 Age 16 19
18 2 Bob 19 2 Frank File1 OBD 1 4
17 1 Candy 18 1 Gill File2 Age 17 19
19 4 Daisy 19 3 Helen File2 OBD 1 3
File3 Age 16 18
File3 OBD 2 4
File4 Age 16 19
File4 OBD 1 4
File
1
Age OBD Name Age File
2
OBD Name
16 4 Ivy 16 2
Meg
18 3 Jim 18 4
Nell
17 2 Kathy 19 1
Olive
17 4 Lynn 16 3
Polly
File
3
File
4
Meta文件
SELECT * FROM t WHERE age = 17
18. 索引:MinMax索引 + 排序
File Field Min Max
Age OBD Name Age OBD Name File1 Age 16 16
16 1 Alice 17 1 Candy File1 OBD 1 4
16 4 Ivy 17 3 Eric File2 Age 17 17
16 2 Meg 17 2 Kathy File2 OBD 1 4
16 3 Polly 17 4 Lynn File3 Age 18 18
File3 OBD 1 4
File4 Age 19 19
File4 OBD 1 4
File
1
Age OBD Name Age File
2
OBD Name
18 2 Bob 19 4
Daisy
18 1 Gill 19 2
Frank
18 3 Jim 19 3
Helen
18 4 Nell 19 1
Olive
File
3
File
4
Meta文件
SELECT * FROM t WHERE age = 17
SELECT * FROM t WHERE obd = 2
19. Z-Order
多维数据没有天然的有序性,需要将
多维数据映射成一维数据进行比较,
映射的一维数据如何保证各个原始维
度数据的聚集性,决定了Data
Clustering的效果。
Z-Value
如何将Int/Long/String/Date/TimeStamp等各种类
型数据转化为正整数进行Interleave Index计算?
20. Z-Order – 保序映射
比特位的保序性:
数据和其参与计算z-
value的比特位顺序保
持一致。
21. Z-Order – 保序映射
Int:首位比特逆转
Long:首位比特逆转 + 前32位比特
转换参与z-value值计
算的比特位,使其和
数值本身保序。
将数据保序地映射成
正整形参与z-value计
算
Float:首位比特逆转
String:前四位字符ASICI
Date:同String
Timestamp:同Long
22. Z-Order – 保序映射的缺陷
1. 从原始值到映射值的保序
映射可能会丢失数值信息,
例如,String类型取前几
位。
2. 映射值的分布无法控制,
导致z-value不符合Z-
ORDER曲线。
例如x取值是[0, 1, 2, 3, 4, 5, 6, 7], y取值是[8, 16, 24,
32, 40, 48, 56, 64], 计算出来的z-value排序结果实际上
和数据按照Order By y, x排序的效果是一样的。
23. Z-Order – Boundary-based interleave index
Spark RangePartitioner的实现机制:
1. 数据采样阶段:
Z-Order增加了一种新的Ordering实现:使
使用采样算法从数据源采样数据, 用采样算法从数据源采样数据,针对每一
根据Ordering对数据进行排序,按照 个参与Z-Order排序字段,按照字段天然顺
shuffle partition数量筛选partition 序排序并筛选field boundaries。实现新的
boundaries。 ordering,每个参与Z-Order排序字段根据
2. 数据处理阶段: field boundaries算出的index参与z-value计
在shuffle阶段数据按照Ordering和
partition boundaries比较,判断所属
的partition。
算,用于ordering排序。
24. Z-Order – 效果
25. Hibert Curve Order
Z-Order曲线
Hibert曲线
26. Z-Order – 效果
27. MinMax + Z-Order On SSB Result
SSB读文件数量
4000 2
2000 1
0
0
Q1.1
Q1.2
Q1.3
Q2.1
Q2.2
Q2.3
Q3.1
basic
Q3.2
Q3.3
Zorder+MinMax
Q3.4
Q4.1
Q4.2
Q4.3
Q5.1
Q5.2
Skip比例
SSB查询速度
50
20
0
0
Q1.1
Q1.2
Q1.3
Q2.1
Q2.2
Q2.3
basic
Q3.1
Q3.2
Q3.3
Zorder+MinMax
Q3.4
Q4.1
加速比例
Q4.2
Q4.3
Q5.1
Q5.2
28. MinMax + Z-Order On SSB Result
Q5.1
SELECT count(*) FROM lo_flatten_ic
WHERE lo_ordtotalprice = 26250978;
Q5.2
SELECT count(*) FROM lo_flatten_ic
WHERE lo_ordtotalprice >= 26250978
and lo_ordtotalprice < 26250979;
1.
2.
Zorder排序字段越多,效果越差,
建议2-4个。
.不进行数据组织排序,MinMax索
引的过滤效果非常有限
ALTER TABLE lo_flatten_ic WRITE
DISTRIBUTE BY s_city, c_city, p_brand, d_datekey WITH ZORDER
LOCALLY ORDERED BY d_datekey
29. 04
索引的增强
30. BloomFilter索引
SSB读文件数量
4000
CREATE INDEX lo_ordtotalprice_bf USING BLOOMFILTER ON
lo_flatten_ic(lo_ordtotalprice)
3000
2000
1000
0
Q5.1
Q5.1
SELECT count(*) FROM lo_flatten_ic WHERE
lo_ordtotalprice = 26250978;
Q5.2
SELECT count(*) FROM lo_flatten_ic WHERE
lo_ordtotalprice >= 26250978 and lo_ordtotalprice <
26250979;
basic
Q5.2
MinMax
BloomFilter
SSB查询速度
40
30
20
对于高基数字段,无需数据排序,对于
等值查询也可以有很好的Data Skip效果。
对于范围查询?
10
0
Q5.1
basic
Q5.2
MinMax
BloomFilter
31. Bitmap索引:Equality Encoded
s_city
c_city
lo_ordtotalprice
UNITED KI001 UNITED ST003 20
UNITED KI007 UNITED ST003 18
UNITED KI001 UNITED ST004 2
UNITED KI007 UNITED ST004 33
UNITED KI001 UNITED ST004 18
UNITED KI007 UNITED ST005 33
UNITED KI001 UNITED ST005 33
UNITED KI007 UNITED ST005 188
UNITED KI007 UNITED ST005 50
数据文件
Bitmap索
引
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
lo_ordertotalprice < 19
2: 001000000
OR
18: 010010000
011010000
Bitmap cardinality > 0, 包含数据
32. Bitmap索引:Equality Encoded – 索引交并运算
Bitmap索
引
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
lo_ordtotalprice < 19 AND c_city = 'UNITED ST005'
2: 001000000
OR
18: 010010000
011010000
c_city
UNITED ST003
UNITED ST004
UNITED ST005
0
1
0
0
1
1
0
0
2
0
1
0
3
0
1
0
4
0
1
0
5
0
0
1
6
0
0
1
7
0
0
1
8
0
0
1
AND
UNITED ST005: 000001111
000001111
000000000
Bitmap cardinality = 0, 不包含数据
33. Bitmap索引:Equality Encoded – 问题
Bitmap索引
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
范围过滤需要访
问计算大量
Bitmap,影响查
询效率
每个基数都要存
储对应的Bitmap,
存储代价太大
34. Bitmap索引:Range Encoded
Equality Encoded Bitmap
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
Range Encoded Bitmap
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
B(n) = RB(n) andNot RB(n-1)
B(<n) = RB(n)
B(>n) = RB(max) andNot RB(n)
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
1
1
1
1
0
1
1
1
1
1
2
1
1
1
1
1
1
3
0
0
0
1
1
1
4
0
1
1
1
1
1
5
0
0
0
1
1
1
范围过滤需要访
问大量Bitmap,
影响查询效率
6
0
0
0
1
1
1
7
0
0
0
0
0
1
8
0
0
0
0
1
1
35. lo_ordtotalpric
0 1 2 3 4 5 6 7 8
e
Bitmap索引:Bit-Slice Encoded
(Comp 0) - 0
Equality Encoded Bitmap
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
1 0 0 0 0 0 0 0 1
1
2
3
4
5
6
7
8
9
(Comp 1) - 0
(comp 2) - 0
Cardinality: 256
Equality Encoded Bitmap Num: 256
Bit-Slice Encoded Bitmap Num: 3*10 = 30
0
0
0
0
0
0
0
1
0
0
1
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0 0 1 0 0 0 0 0 0
1
2
3
4
5
6
7
8
9
Bit-Slice Encoded Bitmap
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
1
0
0
0
0
1 1 1 1 1 1 1 0 1
1
2
3
4
5
6
7
8
9
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
36. lo_ordtotalprice 0 1 2 3 4 5 6 7 8
(Comp 0) - 0 1 0 0 0 0 0 0 0 1
Bitmap索引:Bit-Slice Range Encoded
11 0 0 0 0 0 0 0 1
21 0 1 0 0 0 0 0 1
31 0 1 1 0 1 1 0 1
41 0 1 1 0 1 1 0 1
51 0 1 1 0 1 1 0 1
61 0 1 1 0 1 1 0 1
Equality Encoded Bitmap
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
71 0 1 1 0 1 1 0 1
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
8
0
0
0
0
1
0
81 1 1 1 1 1 1 1 1
91 1 1 1 1 1 1 1 1
(Comp 1) - 0 0 0 1 0 0 0 0 0 0
10 1 1 0 1 0 0 0 0
Bit-Slice Range Encoded Bitmap
21 1 1 0 1 0 0 0 0
31 1 1 1 1 1 1 0 0
41 1 1 1 1 1 1 0 0
51 1 1 1 1 1 1 0 1
61 1 1 1 1 1 1 0 1
71 1 1 1 1 1 1 0 1
81 1 1 1 1 1 1 1 1
91 1 1 1 1 1 1 1 1
(comp 2) - 0 1 1 1 1 1 1 1 0 1
11 1 1 1 1 1 1 1 1
21 1 1 1 1 1 1 1 1
Cardinality: 256
Equality Encoded Bitmap Num: 256
Bit-Slice Encoded Bitmap Num: 3*9 + 1 = 28
31 1 1 1 1 1 1 1 1
41 1 1 1 1 1 1 1 1
51 1 1 1 1 1 1 1 1
61 1 1 1 1 1 1 1 1
71 1 1 1 1 1 1 1 1
81 1 1 1 1 1 1 1 1
91 1 1 1 1 1 1 1 1
37. Bitmap索引:Comp-2 Bit-Slice Range Encoded
lo_ordtotalprice 0 1 2 3 4 5 6 7 8
(Comp 0) - 0 1 1 1 0 1 0 0 1 1
Equality Encoded Bitmap
lo_ordtotalprice
2
18
20
33
50
188
0
0
0
1
0
0
0
1
0
1
0
0
0
0
2
1
0
0
0
0
0
3
0
0
0
1
0
0
4
0
1
0
0
0
0
5
0
0
0
1
0
0
6
0
0
0
1
0
0
7
0
0
0
0
0
1
1 1 1 1 1 1 1 1 1 1
8
0
0
0
0
1
0
(Comp 1) - 0 1 0 0 1 0 1 1 1 0
1 1 1 1 1 1 1 1 1 1
(Comp 2) - 0 0 1 1 1 1 1 1 0 1
Comp-2 Bit-Slice Range
Encoded Bitmap
1 1 1 1 1 1 1 1 1 1
(Comp 3) - 0 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
(Comp 4) - 0 0 0 1 1 0 1 1 0 0
1 1 1 1 1 1 1 1 1 1
(Comp 5) - 0 1 1 1 0 1 0 0 0 0
O(n)
O(log(n))
Cardinality: 256
Equality Encoded Bitmap Num: 256
Comp-2 Bit-Slice Encoded Bitmap Num: 1 * 8 + 1 = 9
1 1 1 1 1 1 1 1 1 1
每个基数都要存
储对应的Bitmap,
存储代价太大
(Comp 6) - 0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
(Comp 7) - 0 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
38. Bitmap Index SSB Result
SSB读文件数量
4000
3000
2000
CREATE INDEX lo_ordtotalprice_bm USING BITMAP
1000
0
Q5.1
ON lo_flatten_ic (lo_ordtotalprice)
basic
Q5.2
MinMax
BloomFilter
Bitmap
SSB查询速度
40
30
20
10
0
Q5.1
basic
Q5.2
MinMax
BloomFilter
Bitmap
39. Final Test Result
1 – 10倍的查询性能提升
SSB查询时间(s)
60
40
20
0
Q1.1
Q1.2
Q1.3
Q2.1
Q2.2
basic
Q2.3
Q3.1
Zorder+MinMax
Q3.2
Q3.3
Zorder+BloomFilter
Q3.4
Q4.1
Q4.2
Q4.3
Q5.1
Q5.2
Zorder+Bitmap
2 – 400倍的读文件减少
SSB读文件数量
4000
3000
2000
1000
0
Q1.1
Q1.2
Q1.3
Q2.1
Q2.2
basic
Q2.3
Q3.1
Zorder+MinMax
Q3.2
Q3.3
Zorder+BloomFilter
Q3.4
Q4.1
Zorder+Bitmap
Q4.2
Q4.3
Q5.1
Q5.2
40. SQL扩展
配置Iceberg表数据分布
ALTER TABLE tableIdentifier WRITE
[DISTRIBUTED BY [PARTITION | distribute_expression [ , distribute_expression [ , ... ] ]
[WITH HASH | RANGE | ZORDER | HIBERTCURVE] ]]
[LOCALLY? ORDERED BY order_expression [ , order_expression [ , ... ] ] | UNORDERED]
配置Iceberg表索引
CREATE INDEX identifier USING (BITMAP | BLOOMFILTER) ON tableIdentifier(column)
DROP INDEX identifier ON tableIdentifier
SHOW INDEX ON tableIdentifier
执行数据优化/生成/删除索引
Actions.forTable(t).optimize.filter(...).execute
Actions.forTable(t).writeIndices.filter(...).indices(...).execute
Actions.forTable(t).dropIndices .filter(...).indices(...).execute
文件间排序
文件内排序
41. 多维分析场景下的配置策略
1个过滤字段
2-4个过滤字段 >4个过滤字段
全局排序 Zorder Distribution 最常用4个过滤字段ZOrder Distribution
超高基数字段加BloomFilter索引 Sort By最常用过滤字段 Sort By最常用过滤字段
超高基数字段加Bitmap索引 其他高基数字段只有等值过滤加BloomFilter索
引,有范围过滤加Bitmap索引
支持任意多字段,任意过滤类型,在绝大部分多维分析场景下,只访问尽量少的
文件,加速查询。
42. 非常感谢您的观看
43. Z-Order – Boundary-based interleave index
44. 索引的代价
文件大小:200M
s_regio
n s_natio
n s_city c_region c_nation c_city p_mfgr p_catego
ry
p_brand d_ye
d_ye d_wee armo
armo knumi nthnu lo_quant lo_disc
ity
ount
d_year nth
nyear m 5 25 2525 5 25 2525 50 2500 752859 7 80 53 80 50 11 41353908
BloomFi 16
lter 文件
大小 16 328 16 16 328 16 168 47016 16 24 56 24 48 24 1145408
Bitmap
文件大
小 399862 1751151 390251 392688 1751148 398350 1554780 3420348 328 749 1653 809 1173326 784140
字段
字段基
数
392288
SSB scale 1000
ORC存储: 542G
记录数:6,000,000,000
Spark集群:716G memory, 160 cores
生成BloomFilter索引:18分钟
生成Bitmap索引:42分钟
lo_ordtotal
price
10586681