30 问最后一篇了,希望这 30 问能解答大家在使用 Apache Doris 或者选择 Apache Doris 的时候产生的各种疑虑。
在 Doris 内,是通过 null 值 与 "" 值来区分的,一个在 CSV 中是类似 \N 这样的值,一个是无数据的,一个是空字符串,这两个值在存储到 Doris 中以后是不一样的,空字符串无法通过 is null 或者 is not null 来做过滤,同时如果导入有默认值的话,那么空字符串不会生成默认值。
当前不可以,如果太过高频的数据插入,会让 Doris 的数据版本合并压力骤增,关于这个问题有两点可以表述的:
1. 我们正在做服务端攒批的能力,换而言之就是把客户端单次提交数据量需要几千几万攒批这个事,交由服务端来做,这样的好处是从用户体感上而言,Doris 是可以支持高频的并发插入能力了,但从实际的数据可见性延迟来看,还是最少要保证 1S 左右的数据延迟。
2. 如果要用 INSERT INTO VALUES 这样的方式进行插入的话,要尽可能多的做数值拼接,也就是 VALUES 的值要多,一般我们建议在 5000-20000 条一个批次,每次导入的综合时延应该在秒级(1-10s),这个和集群本身的配置有关,比如磁盘的 IO 能力等。
当前不支持优先级设置,但是这个在 Doris 查询层做了很多工作来保证。
1. 查询内存硬限:在 1.1.2 开始,Doris 开始使用 MemTracker 来做统一的内存申请管理,本身 Doris 是一款 MPP 架构数据库,在计算的时候会比较依赖内存来做高速缓存,所以如果内存申请不够,复杂 SQL 可能是无法执行的,这会保证整个集群不会因为某个大 SQL 直接吃完所有的内存而饿死小查询,这个硬限默认 2G,如果想调整单次查询的内存申请大小,可以通过 SET exec_mem_limit=4g; 这样的语句来申请硬限。
2. 查询内存软限:在 1.2.0 开始,MemTracker 的限制默认策略从硬限变为了软限,软限就是会尽可能从当前集群申请内存,来满足大查询的要求,而不必再预估单次大查询到底要多少 G 内存才行,使用体感会好很多,如果一个大查询发下来,本来需要 20G 内存,当前可用内存只有 12G,那么会在接下来 5 秒内尽可能的清理内存空间,如果 5 秒内能清理出来,满足运行内存大小,那么就执行,如果清理不出来,就 cancel 该查询,那如果想回到硬限策略,可以在 BE 配置文件中设置 enable_query_memory_overcommit=false 即可关闭软限,打开硬限。
3. 引入数据队列机制:在火山模型的串行机制下,数据扫描到聚合的过程,有 IO 和 CPU 没有并行执行的缺陷,那么在 Doris 内部,设计了在 scan 底下,增添一个双循环队列,这个双循环队列可以有效的解决并行执行问题,而且相较于增添一个数据队列,还解决了大查询饿死小查询、OOM 等问题,这是在底层设计层面的优化手段。
4. 限制单个用户的并发度:在 Doris 内部,默认给一个用户是 100 的并发度,这个可以使用 max_user_connectors 来进行调整,如果有资源限制诉求,调整这个并发度可以有效的解决某些用户可能会错误使用查询导致整个集群负载过高的问题。
Doris join 好的原理如果展开来讲,可能篇幅会非常之广,这里只做简明扼要的答疑,如果有对更详细的知识点感兴趣的看官老爷,可以移步至 Apache Doris 官网查看 JOIN 优化相关的篇章。
那么这个问题省流答疑就是——在 JOIN 方面有大量的优化手段和底层设计。
1. 两种 JOIN 物理算子:Hash Join & Nest Loop Join,前者仅限于等值 JOIN但性能好,后者更通用但性能差。
2. 选择合适的 Shuffle 方式:上述的 Shuffle 方式从上到下适用场景越来越窄,但是效率越来越高,所以在编写查询 SQL 时,应当从这些方面入手来优化。所以根据以上的 Shuffle 设计以及还有很多相关设计,Doris 可以做到 MPP 架构下的快速 JOIN 查询。
1. Broadcast Join:支持 Hash Join 和 Nest loop Join,主要是把右表的数据全量发送给左表,然后进行关联,这种数据传输的成本最高,效率最低,但是适用场景最广。
2. Shuffle Join:仅支持 Hash Join,然后根据 Join 的条件,选择该列进行 Hash 计算,左右表数据根据 Hash 分区将计算结果进行分发。
3. Bucket Shuffle Join:仅支持 Hash Join,如果 Join 的条件列为左表的分桶列,只需要右表根据左表分区计算的结果发送到左表扫描的节点即可完成 Join 计算。
4. Colocate:仅支持 Hash Join,数据进行预分区,如果 Join 条件下左右表的分桶数据都在同节点,那么就免去了 Shuffle 的传输损失,直接本地 Join 即可。
先说一个我们认为是长期愿景且为之努力的目标:
在未来五到十年,将 Apache Doris 打造成 OLAP 领域的工业界标准,努力看齐 OLTP 领域的 MySQL & Oracle!
这个愿景是整个社区都为之努力的一个目标,那么在细粒度来看,我们生存发展策略和前景在我们眼里,又是如何的呢?
首先谈生存发展策略,我们认为在未来的数据分析领域,一定是要求数据时效性越来越高、数据可靠性越来越高、维护复杂性越来越低、架构复杂度越来越低的趋势,那么 Apache Doris 我们定义为新一代的实时数据仓库的根本原因也在这里。
关键词有几个:
1. 实时:什么叫实时?我认为只有从数据导入到数据 ELT 到数据查询都实时化,才能算是实时。但这里我也要阐述三点观点:
1. 实时这件事的区分限度很模糊,有些同学认为分钟级就是实时了,有些同学认为毫秒级才算实时,而从我的角度而言,我认为只要能满足业务最低诉求的实时时效性,那么企业内部的数据实时化就是成功的,比如一个 BI 看板上的某个数值,在绝大部分的实际场景里,1 秒看到和 1 分钟看到其实差别不大,但是要实现 1 秒看到和 1 分钟看到两者要求的技术力、消耗的资源等,都不是一个量级的,所以我认为合理区间内的实时化才是当前企业应当追寻的东西。
2. 不是所有数据都需要实时,上面也阐述了,本身实时化的数据在当前计算硬件资源的投入成本、产出价值等多维度综合考虑下,就是需要衡量一个平衡点的,所以有选择的实时化,才能为企业真正的提升生产效率和降低成本,一股脑的追寻全域实时化,其实往往会得不偿失。
3. Doris 现在可以实现最低 500ms 的导入延迟,在绝大部分场景下是可以满足实时诉求的,同时导入由于是事务性的,所以本身是导入即可见的,这一点也是实时标准,再一方面如果要进行指标聚合或者数据更新的话,利用 Unique Key 模型或者 Agg 模型,在导入过程中就完成了计算,那么查询时的效率会进一步提升,至于查询阶段,Doris 有 MPP 加持,有向量化引擎加持,有 CBO&RBO 加持,计算速度也是实时的,所以综合下来,Apache Doris 是在实时这一块非常能打的一款数据库产品。
2. 数据仓库:在面对海量数据的查询和统计分析的场景下,需要不仅仅是分析查的快,还要在传统 ETL/ELT 离线处理里也要耐打,在这一点 Doris 也做了不少功课:
1. 部分算子落盘
2. 大批裁小批
3. ETL Queue
1. 本身基于强大的计算性能,可以完成内表及外表的各种关联计算,速度比 Hive On MR 和 Hive On Spark 都要快不少。
2. 为了更健壮,未来还会做三件事保证 ETL/ELT 场景的稳定性:
4. 轻量级:希望更少的组件就可以覆盖更多的场景,也希望在后续运维和使用过程中能更省心,那么 Doris 也是可以胜任的:
1. 简单好用的扩缩容能力,无需人工干预 Reblance。
2. 不依赖任何其他组件,只有 FE 和 BE 两个进程,部署运维成本极低。
3. 强大的自愈能力,如果多副本情况下出现数据副本损耗,会定期自动调度修复,无需人工干预。
4. 数据自动均衡能力,有负载均衡和磁盘间均衡的加持,无需担心数据大幅度倾斜问题。
那么前景如何呢?
Doris 当前全球已经有两千多家用户了,这个数字在去年年初是三百家,同时 Doris 连续十个月蝉联全球 Apache 大数据项目活跃度第一的 Title,现在月活跃贡献者已经一百多人了,要比 15-16 年 Apache Spark 项目最火的时候的活跃人数还要多,所以 Apache Doris 一定是未来更多人的选择,也是更多企业在后续招人时候的一项必面技术栈了,打个广告,关注 Apache Doris 补习班,让你无惧 Doris 面试 ^_^
Doris 内部存储是借鉴了 HDFS 的存储机制的,是有副本概念的,集群默认是 3 副本来保证数据的高可用和高可靠,同时内部的自我修复机制,可以保证同一 Tablet 的某个副本损坏后,根据多数派原则来进行坏副本修复,这些是无需感知和干预的。
Doris 的存储是多级连形式存储具体的物理数据的。
首先是存储的目录,这个由 be.conf 中的 storage_root_path 来配置,在这个目录下,下一层按照 Bucket 来进行组织,在 Bucket 目录下,又根据 Tablet 来进行划分,用 tablet_id
来命名目录,那么最后在 Tablet 目录下存放实际的 Segment 数据物理文件。
Segment 物理文件默认大小是 256MB,格式分三部分,一部分是数据区域,存放具体数据,一部分是索引区域,存放 Index 数据,还有一部分是 Footer 信息,主要是存放元数据相关的信息。
高并发点查是利用 2.0 版本里的行列混存来实现的,在高并发点查的情况下有几种方式来保证资源隔离避免互相争抢导致的问题:
1. 设置单个用户的最大可用连接数,尽可能保证单个用户不会将资源吃光。
2. 采用副本分组的多租户模式,将高并发点查和 AdHoc 查询的数据资源划分开来,避免资源争抢。
3. 高并发点查本身单位查询下吃的资源不多,那么如果并发度不是特别高的情况下,其实对 AdHoc 的影响不是很大,反而要考虑 AdHoc 是否会影响高并发点查的查询时延。
4. 资源充足的情况下,使用多个集群来进行隔离。
本身删除数据对 Doris 而言相当于一次导入动作,所以不建议频繁的删除。
如果是大批量数据更新的时候,建议使用以下几种操作来处理:
1. 利用 AGG 模型的 REPLACE_IF_NOT_NULL 和 Unique Key 模型的 REPLACE 算子来完成数据的更新,这种更新无需考虑手工处理,往里灌数据即可。
2. 使用临时分区替换原有分区来完成数据大批量更新,这种适合以分区粒度级的数据更新,先创建临时分区,再 DROP 老分区,替换新分区。
当前在 1.2.4.1 版本及以后版本里,都可以使用 Hive Catalog
的联邦查询能力加 INSERT INTO SELECT
语句来完成数据从外表到内表的灌入,这个灌入的效率非常快,适合定期调度脚本来同步增量的数据。
如果是大批量的数据迁移,那么在后续的 X2Doris 工具可以很好的完成这件事,X2Doris 是 Apache Doris 社区的王华杰大佬(也是 Apache StreamPark Chair)的杰作,已经处于内测阶段了,本身工具是带可视化界面的,还可以做 DDL 的可视化迁移和重新设计工作,可以极大的降低迁移工作成本。
来自用户的这三十问还是比较有难度的,希望能通过这次答疑来给大家带来一些知识收获。后续 Apache Doris 补习班还是会更多的尽可能给大家带来简洁明了但充满知识干货的系列文章,或许你要参加的下一个面试的面试官,就在这里找他问你的问题哦 ^_^
我的微信号:fl_manyi