构建一个高效的大规模数据系统需要同时考虑(按照重要级别排序):
- 算法的时间复杂度优化
- 内存, cpu, 网络, io等硬件的使用效率
- 系统资源的合理调度
- 代码的可维护性
ETL (Extract - Transform - Load)
用来描述数据从源端经过抽取(extract), 转换(transform), 加载(load)至目标端的过程。最耗时间的是transform
过程。
SQL连接算法
- Nested Loop Join: 嵌套的循环连接, 简单地说就是两层
for
循环根据条件进行匹配(当然会有索引优化) - Hash Join: 观察连接条件的字段, 根据其中一个表的字段建立一个buckets, 然后对另外一个表循环与buckets中的值进行条件匹配
- Sort Merge Join: 先对两个表进行排序, 有了排序关系后就可以更加高效的进行连接(类似与双指针的思想, 一个表一个指针, 根据不同条件移动指针)
SQL窗口函数
常见函数 row_number
, count
, sum
等等…
固定大小rows代表行的固定, range则是窗口内值的固定:
1 | rows 1 preceding 2 following 2 |
SQL递归查询
1 | WITH RECURSIVE cte_name (column_list) AS ( |
SQL优化技巧
- 深入理解数据, 争取从算法逻辑上优化
- 分析每一个计算阶段, 在保证正确性的情况下尽可能使得每一个阶段计算的数据量足够小(过滤无用的数据, 可以用)
- 小表驱动大表
- 索引优化
- 必要时对数据进行分区或者分桶, 提高并行度
- 将算子转化到一些高性能的库(可以是Rust的DataFusion, 快手在做这个)
总结: 因为计算机所有东西都是由信息组成。于是可以通过信息论进行解释, 消除不确定性, 使得编码所需的空间就更加小了,那么就能提高计算机各方面资源的利用率。我喜欢用信息论去理解性能问题。
Hadoop 基础
三大组件:
- hdfs
- mapreduce
- yarn
hdfs三大角色:
- NameNode
- DataNode
- SecondNameNode
hdfs文件格式:
- Text File (类似csv的行式存储)
- Sequence File (kv序列化存储, 常用于中间数据)
- Avro File (基于行的序列化)
- RC/ORC (列式存储, 支持压缩和切分)
- Parquet (我最喜欢的列式存储, 高压缩)
文件压缩算法: Gzip、bzip2、LZO、LZ4和Snappy
数据仓库(Data Warehouse)
什么是数据仓库, 其实和数据库的本质相似, 都是数据的集合
, 但区别就是所对应数据存储的特点和目的不一样。
数据库(database)存下数据的特点: 有组织, 可共享, 尽可能小的冗余
数据仓库(data warehouse)下数据的特点:
- 面向主题的(Subject Oriented)
- 集成的(Integrated)
- 相对稳定的(Non-Volatile)
- 反映历史的(Time Variant)
为什么需要数据仓库?
复杂问题分解, 提高复用降低计算成本(空间换时间的思想), 可维护性提升.
数据仓库的分层
- ods
- dwd
- dwm
- dws
- apl
数据库三范式
- 原子性, 表中字段的数据不可以再拆分
- 唯一性, 其实就是消除依赖, 一个表只描述一件事情
- 在满足以上2的情况下, 完全消除非主键列的依赖性
数据倾斜问题
什么是数据倾斜? 本质上是由于数据分配给各个集群服务器不均匀导致的, 于是就可能出现某台服务器Task运行时间久或者直接OOM(Out Of Memoey).
解决: 实现要搞清楚Map过程是不会发生数据倾斜的, 因为 hdfs 都帮我们分成了 128 MB 的 block
保证了每台服务器上数据的均匀分配。发生数据倾斜一般是在 Shuffle 这个过程, 因为这个过程负责混洗和分区, 可能会造成分区到一台机器的数据量就过多了, 也有可能分区到其它机器的数据量极其少。
AI的答案:
- 空值处理:在进行表连接时,可以通过过滤或赋予空值新的key值来避免数据倾斜。
- 数据类型统一:在join操作中,确保连接字段的数据类型一致,避免不同数据类型引起的倾斜。
- 大小表连接优化:对于大小表的连接,可以采用map端join,即将小表数据广播到所有节点,避免shuffle操作。
- 两阶段聚合:对于group by操作导致的数据倾斜,可以使用两阶段聚合,即先局部聚合再全局聚合,通过增加随机前缀打散key值。
- count distinct优化:对于count distinct操作,可以将空值单独处理或使用sum() group by来替代。
- 排序优化:对于排序操作,可以考虑是否只有一个reducer在工作,如果是,则可能需要增加reducer数量或调整策略。
其它问题
- MapReduce三个过程?
Input Splitting -> Mapping -> Shuffling and Sorting -> Reduce. - MapReduce中为什么需要 Shuffle?
确保下一步能够并行处理(利益最大化), 相同键的键值对分配到同一个Reduce任务中. 排序确保Reduce任务能够按照key的顺序进行处理 - 为什么把任务写入环形内存缓冲区?
减少频繁的磁盘I/O操作. 并行处理. - Hadoop中fsimage和edit的区别是什么?
fsimage是静态(历史)的, edit是动态(实时)的. - Hadoop的Combiner的作用?
在Map阶段之后,在数据传输到Reduce阶段之前对Map输出的中间劫夺进行本地合并和压缩,以减少数据的传输量和提高整体的性能。Combiner可以将相同key的多个Map输出结果进行合并,减少了网络传输的数据量.