diff --git a/README.md b/README.md index 6ae4dd4..f513731 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

与 Databend 一同探秘数据库系统

- 在线阅读 | + 在线阅读 | 查看源码 | 前往 Databend

diff --git a/docs/config.toml b/docs/config.toml index 4bfe13a..5ecfdf9 100644 --- a/docs/config.toml +++ b/docs/config.toml @@ -1,5 +1,5 @@ # The URL the site will be built for -base_url = "https://psiace.github.io/databend-internals" +base_url = "https://databend-internals.psiace.me" title = "Databend 内幕大揭秘" description = "与 Databend 一同探秘数据库系统" diff --git a/docs/content/docs/contribute-to-databend/build-and-more.md b/docs/content/docs/contribute-to-databend/build-and-more.md index ba60f62..723294a 100644 --- a/docs/content/docs/contribute-to-databend/build-and-more.md +++ b/docs/content/docs/contribute-to-databend/build-and-more.md @@ -19,7 +19,7 @@ giscus = true Databend 在 `Makefile` 中封装了大量常见命令。采用 make 构建只会开启默认特性,并且会一次性构建 `databend-meta`、`databend-query` 以及 `databend-metactl` 。 -按 [前文](https://psiace.github.io/databend-internals/docs/contribute-to-databend/development-environment/) 设置好开发环境后。 +按 [前文](https://databend-internals.psiace.me/docs/contribute-to-databend/development-environment/) 设置好开发环境后。 - 执行 `make build` 即可轻松构建 debug 版本。 - `make build-release` 则会构建 release 版本,并会采用 objcopy 减少二进制体积。 diff --git a/docs/content/docs/contribute-to-databend/how-to-benchmark.md b/docs/content/docs/contribute-to-databend/how-to-benchmark.md index b50a9eb..a7a2e80 100644 --- a/docs/content/docs/contribute-to-databend/how-to-benchmark.md +++ b/docs/content/docs/contribute-to-databend/how-to-benchmark.md @@ -286,20 +286,20 @@ pattern ='.*[.]csv' file_format=(type='CSV' field_delimiter='\t' record_delimite **Graphs** -![graphs](https://psiace.github.io/databend-internals/contribute-to-databend/how-to-benchmark/01-graph.png) +![graphs](https://databend-internals.psiace.me/contribute-to-databend/how-to-benchmark/01-graph.png) - 以折线图的形式展示性能变化,并支持通过拖动图表下方的选择器调整展示的时间区间。 - 横轴为日期,纵轴为执行用时,鼠标悬浮到上方即可查看当次执行的信息。 **Compare** -![compare](https://psiace.github.io/databend-internals/contribute-to-databend/how-to-benchmark/02-compare.png) +![compare](https://databend-internals.psiace.me/contribute-to-databend/how-to-benchmark/02-compare.png) - 支持任选两天对比执行用时的变化,以百分比形式展示。 **Status** -![status](https://psiace.github.io/databend-internals/contribute-to-databend/how-to-benchmark/03-status.png) +![status](https://databend-internals.psiace.me/contribute-to-databend/how-to-benchmark/03-status.png) - 关注当前最新性能测试结果中各指标的情况,以柱型图展示。 - 横轴为不同类型,纵轴为执行用时。 diff --git a/docs/content/docs/contribute-to-databend/how-to-contribute.md b/docs/content/docs/contribute-to-databend/how-to-contribute.md index a1b7817..baeedcd 100644 --- a/docs/content/docs/contribute-to-databend/how-to-contribute.md +++ b/docs/content/docs/contribute-to-databend/how-to-contribute.md @@ -71,7 +71,7 @@ Slack: **前置环境** -在「[Databend 贡献之路 | 如何设置 Databend 开发环境](https://psiace.github.io/databend-internals/docs/contribute-to-databend/development-environment/)」一文中,已经详细介绍过如何配置 Databend 开发环境。 +在「[Databend 贡献之路 | 如何设置 Databend 开发环境](https://databend-internals.psiace.me/docs/contribute-to-databend/development-environment/)」一文中,已经详细介绍过如何配置 Databend 开发环境。 需要注意的是,考虑到不同系统和发行版之间的差异,你可能需要自行安装 `gcc`,`python` 和 `openssl` 等相关基础程序。 @@ -144,7 +144,7 @@ cargo audit **测试** -在「[Databend 贡献之路 | 如何为 Databend 添加新的测试](https://psiace.github.io/databend-internals/docs/contribute-to-databend/write-and-run-tests/)」中,已经对测试做了详细的描述。 +在「[Databend 贡献之路 | 如何为 Databend 添加新的测试](https://databend-internals.psiace.me/docs/contribute-to-databend/write-and-run-tests/)」中,已经对测试做了详细的描述。 通常情况下,使用 `make test` 一次性执行 `单元测试` 和 `功能测试` 就可以。 diff --git a/docs/content/docs/contribute-to-databend/how-to-profile.md b/docs/content/docs/contribute-to-databend/how-to-profile.md index 84e9314..0535484 100644 --- a/docs/content/docs/contribute-to-databend/how-to-profile.md +++ b/docs/content/docs/contribute-to-databend/how-to-profile.md @@ -71,7 +71,7 @@ go tool pprof -http=0.0.0.0:8088 ~/pprof/pprof.samples.cpu.001.pb.gz 访问 `http://0.0.0.0:8088/ui/flamegraph` 即可得到火焰图。 -![pprof flamegraph](https://psiace.github.io/databend-internals/contribute-to-databend/how-to-profile/01-pprof-flamegraph.png) +![pprof flamegraph](https://databend-internals.psiace.me/contribute-to-databend/how-to-profile/01-pprof-flamegraph.png) ### 注意事项 @@ -154,7 +154,7 @@ jeprof \ 同样选用 debug 模式下编译的 databend-query 作为 target,端口为 8080,结果如图所示: -![jeprof call graph](https://psiace.github.io/databend-internals/contribute-to-databend/how-to-profile/02-jeprof-mem.png) +![jeprof call graph](https://databend-internals.psiace.me/contribute-to-databend/how-to-profile/02-jeprof-mem.png) ### 注意事项 diff --git a/docs/content/docs/contribute-to-databend/tracing-in-databend.md b/docs/content/docs/contribute-to-databend/tracing-in-databend.md index ab0d496..ea71a0f 100644 --- a/docs/content/docs/contribute-to-databend/tracing-in-databend.md +++ b/docs/content/docs/contribute-to-databend/tracing-in-databend.md @@ -19,7 +19,7 @@ giscus = true ### 初识 Tracing -![Tracing Logo](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/01-tracing.svg) +![Tracing Logo](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/01-tracing.svg) Tracing 是由 Tokio 团队维护的 Rust 应用追踪框架,用来收集结构化的、基于事件的诊断信息。 @@ -137,7 +137,7 @@ Databend 原生提供了多种观测方式,以方便诊断和调试: - 服务依赖性分析 - 性能/延迟优化 -![Opentelemetry & Jaeger](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/02-jaeger-and-opentelemetry.png) +![Opentelemetry & Jaeger](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/02-jaeger-and-opentelemetry.png) ### Step by Step @@ -152,7 +152,7 @@ Databend 原生提供了多种观测方式,以方便诊断和调试: ### 结果探索 -![dot graph](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/03-jaeger-dot-graph.png) +![dot graph](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/03-jaeger-dot-graph.png) _x 轴是执行时刻,y 轴是持续的时间,圆点反映 span 的聚集程度。_ @@ -168,19 +168,19 @@ INSERT INTO t1 SELECT * FROM t1; 下图是点击最大的圆点得到的追踪情况: -![span tracing](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/04-jaeger-span-tracing.png) +![span tracing](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/04-jaeger-span-tracing.png) 使用 timeline 模式来展现 tracing 的各个跨度之间的关系。以时间为主线进行分析,方便使用者观看在某个时间点观看程序信息。 点开第一个跨度,可以看到这是执行 `INSERT INTO t1 SELECT *FROM t1` 查询时的情况。 -![span info](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/05-jaeger-span-info.png) +![span info](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/05-jaeger-span-info.png) **Graph** 切换到 graph 模式,可以看到各个 span 之间的调用链,每个 span 具体用时 ,以及百分比。 -![span graph](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/06-jaeger-span-graph.png) +![span graph](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/06-jaeger-span-graph.png) 通过这个视图使用者很容易知道系统瓶颈,快速定位问题。 @@ -188,7 +188,7 @@ INSERT INTO t1 SELECT * FROM t1; 连起来的各个部分形成整个 trace 的调用链。因为比较时一般会比较两个相同类型的调用,所以看到的会是重合后的视图。 -![span compare](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/07-jaeger-span-compare.png) +![span compare](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/07-jaeger-span-compare.png) 对于颜色的一个说明: @@ -203,7 +203,7 @@ tokio-rs 团队出品的诊断和调试工具,可以帮助我们诊断与 toki ### console 是什么 -![tokio console](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/08-tokio-console.png) +![tokio console](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/08-tokio-console.png) tokio-console 是专为异步程序设计的调试与诊断工具,能够列出 tokio 的任务,提供对程序的任务和资源的实时、易于导航的视图,总结了它们的当前状态和历史行为。主要包含以下组件: @@ -229,13 +229,13 @@ tokio-console 是专为异步程序设计的调试与诊断工具,能够列出 1. 任务是一个轻量级的、非阻塞的执行单元。类似操作系统的线程,但是是由 tokio 运行时管理,一般叫做“绿色线程”,与 Go 的 goroutine,Kotlin 的 coroutine 类似。 2. 任务是协同调度的。大多数操作系统实现抢占式多任务。操作系统允许每个线程运行一段时间,然后抢占它,暂停该线程并切换到另一个线程。另一方面,任务实现协同多任务。一个任务被允许运行直到它让出执行权,运行时会切换到执行下一个任务。 -![tokio console basic](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/09-tokio-console-basic.png) +![tokio console basic](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/09-tokio-console-basic.png) **基础视图** 通过左右切换,可以得到总忙时间或轮询次数等指标对任务进行排序。控制台通过高亮来提示较大差异,比如从毫秒到秒的切换。 -![tokio console sort](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/10-tokio-console-sort.png) +![tokio console sort](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/10-tokio-console-sort.png) 控制台还实现了一个“警告”系统。通过监视应用程序中任务的运行时操作,控制台可以检测可能提示 bug 或性能问题的行为模式,并突出显示这些行为模式供用户分析。比如已经运行了很长时间而没有让步的任务,唤醒的次数比被其他任务唤醒的次数还要多的任务。 @@ -243,7 +243,7 @@ tokio-console 是专为异步程序设计的调试与诊断工具,能够列出 上下切换选中任务,enter 查看关于每个任务的翔实数据,比如轮询持续时间的直方图。 -![tokio console task](https://psiace.github.io/databend-internals/contribute-to-databend/tracing-in-databend/11-tokio-console-task.png) +![tokio console task](https://databend-internals.psiace.me/contribute-to-databend/tracing-in-databend/11-tokio-console-task.png) 不仅列出任务。console 还会插入异步互斥和信号量等资源。Tokio Console 的资源详细信息视图显示了哪些任务已经进入临界区,哪些任务正在等待获得访问权限。 diff --git a/docs/content/docs/contribute-to-databend/write-and-run-tests.md b/docs/content/docs/contribute-to-databend/write-and-run-tests.md index e6c9998..72c902d 100644 --- a/docs/content/docs/contribute-to-databend/write-and-run-tests.md +++ b/docs/content/docs/contribute-to-databend/write-and-run-tests.md @@ -13,7 +13,7 @@ top = false giscus = true +++ -> 在「[产品力:Databend 的质量保障](https://psiace.github.io/databend-internals/docs/productivity-topics/quality-assurance-in-databend/)」一文中,已经介绍到组成 Databend 测试的两个重要部分 —— 单元测试和功能测试。如有遗忘,不妨回顾一下。 +> 在「[产品力:Databend 的质量保障](https://databend-internals.psiace.me/docs/productivity-topics/quality-assurance-in-databend/)」一文中,已经介绍到组成 Databend 测试的两个重要部分 —— 单元测试和功能测试。如有遗忘,不妨回顾一下。 ## 单元测试 diff --git a/docs/content/docs/getting-started/introduction.md b/docs/content/docs/getting-started/introduction.md index 8e33670..718bddc 100644 --- a/docs/content/docs/getting-started/introduction.md +++ b/docs/content/docs/getting-started/introduction.md @@ -36,4 +36,4 @@ giscus = true ## 协作 -「Databend 内幕大揭秘」的内容完全开源,有意向参与协作和贡献的,请参考「[贡献相关](https://psiace.github.io/databend-internals/docs/contributing/)」一节的内容。 +「Databend 内幕大揭秘」的内容完全开源,有意向参与协作和贡献的,请参考「[贡献相关](https://databend-internals.psiace.me/docs/contributing/)」一节的内容。 diff --git a/docs/content/docs/minibend/datasource.md b/docs/content/docs/minibend/datasource.md index 4692cad..39832cd 100644 --- a/docs/content/docs/minibend/datasource.md +++ b/docs/content/docs/minibend/datasource.md @@ -18,7 +18,7 @@ giscus = true > > 视频(哔哩哔哩): > -> PPT: +> PPT: ## 类型系统和 Arrow @@ -36,7 +36,7 @@ giscus = true 解决了数据类型的问题,那么就该考虑数据存储时候的模型。行式存储和列式存储都属于流行的方案,当然,这往往取决于要面对什么样的查询任务。另外还有混合行式和列式存储的方案,但这并不在今天讨论的范畴之中。 -![Column Based](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/04-column-based-vectorwise.png) +![Column Based](https://databend-internals.psiace.me/the-basics/executor-in-query-process/04-column-based-vectorwise.png)

左图可以看作列式存储的一个样本,同一列的数据在内存中形成一个连续的结构。
而行式存储则如右图所示,同一行的数据在内存中是连续的。

diff --git a/docs/content/docs/minibend/intro.md b/docs/content/docs/minibend/intro.md index 80cd086..41bd50e 100644 --- a/docs/content/docs/minibend/intro.md +++ b/docs/content/docs/minibend/intro.md @@ -14,13 +14,13 @@ giscus = true minibend ,一个从零开始、使用 Rust 构建的查询引擎。这里是 minibend 系列技术主题分享的第一期,来自 [@PsiACE](https://github.com/psiace) 。 -![minibend](https://psiace.github.io/databend-internals/minibend/001-basic-intro/minibend-001-basic-intro_01.png) +![minibend](https://databend-internals.psiace.me/minibend/001-basic-intro/minibend-001-basic-intro_01.png) > 前排指路视频和 PPT 地址 > > 视频(哔哩哔哩): > -> PPT: +> PPT: ## minibend: what, why, how @@ -66,7 +66,7 @@ minibend 同时也是 *Databend Internals*,或者说 *Databend 内幕大揭秘 首先,minibend 会提供视频、文章和代码三种材料。文章和代码将会同步到 *Databend 内幕大揭秘* 的 Repo 中,而视频则会发布到 Databend 的 B 站官方帐号下。欢迎大家持续关注。 -> Databend 内幕大揭秘: +> Databend 内幕大揭秘: > > Databend(哔哩哔哩): @@ -84,7 +84,7 @@ minibend 同时也是 *Databend Internals*,或者说 *Databend 内幕大揭秘 但是“存在哪”呢? -![storage Level](https://psiace.github.io/databend-internals/the-basics/storage/01-storage-level.png) +![storage Level](https://databend-internals.psiace.me/the-basics/storage/01-storage-level.png) 过去的一些存储方案更加关注上图所示的存储体系结构,将需要在线处理的数据存放在闪存和硬盘中,用于备份的数据放入光盘和磁带。 @@ -98,7 +98,7 @@ Databend 早期的实现是包含一套分布式文件系统的,但到现在 引入索引的好处在于加快数据查询的速度,而缺点则在于构建和维护索引同样需要付出代价。 -![b tree disk](https://psiace.github.io/databend-internals/minibend/001-basic-intro/01-b-tree-disk.png) +![b tree disk](https://databend-internals.psiace.me/minibend/001-basic-intro/01-b-tree-disk.png) 不同的索引可以针对不同的场景提供优化,B Tree 能够加速范围查询,而等值查询就可以使用 Hash 索引,BitMap(或者说更常用的 Bloom 索引)可以方便判断数据是否存在。 @@ -108,7 +108,7 @@ Databend 的索引无需人为创建,由部署的实例自行维护。同时 尽管有各种各样的查询引擎,但具体到查询执行的环节大同小异,这里以 Databend 为例,简单讲一下过程。 -![Query Steps](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/01-query-steps.png) +![Query Steps](https://databend-internals.psiace.me/the-basics/executor-in-query-process/01-query-steps.png) 1. 解析 SQL 语法,形成 AST(抽象语法树)。 2. 通过 Binder 对其进行语义分析,并且生成一个初始的 Logical Plan(逻辑计划)。 @@ -130,7 +130,7 @@ Databend 的索引无需人为创建,由部署的实例自行维护。同时 下面的图片展现的是一种典型的查询优化,对 JOIN 进行重排。 -![JOIN Reorder](https://psiace.github.io/databend-internals/minibend/001-basic-intro/02-join-reorder.png) +![JOIN Reorder](https://databend-internals.psiace.me/minibend/001-basic-intro/02-join-reorder.png) 目前有两种主要的查询优化方案,一种是基于关系代数和算法的等价优化方案,一种是基于评估成本的优化方案。根据命名,不难看出优化的灵感来源和这两种方案在优化上的取舍。 @@ -147,7 +147,7 @@ Databend 引入了基于规则的 [Cascades 优化器](https://15721.courses.cs. 大规模并行处理是大数据计算引擎的一个重要特性,可以提供高吞吐、低时延的计算能力。那么,当我们在讨论大规模并行处理时,究竟在讨论什么? -![mpp](https://psiace.github.io/databend-internals/minibend/001-basic-intro/minibend-001-basic-intro_12.png) +![mpp](https://databend-internals.psiace.me/minibend/001-basic-intro/minibend-001-basic-intro_12.png) 大规模并行处理(MPP,Massively Parallel Processing)意味着可以由多个计算节点(处理器)协同处理程序的不同部分,而每个计算节点都可能具备独立的系统资源(磁盘、内存、操作系统)。 @@ -157,7 +157,7 @@ Databend 引入了基于规则的 [Cascades 优化器](https://15721.courses.cs. ### 分布式 -![分布式](https://psiace.github.io/databend-internals/minibend/001-basic-intro/minibend-001-basic-intro_13.png) +![分布式](https://databend-internals.psiace.me/minibend/001-basic-intro/minibend-001-basic-intro_13.png) 从某种视角上看,分布式系统与 MPP 系统有着惊人的相似。比如:通过网络连接、对外作为整体提供服务、计算节点拥有资源等。但是这两种架构仍然会有一些不同。 @@ -171,7 +171,7 @@ Databend 引入了基于规则的 [Cascades 优化器](https://15721.courses.cs. ### The Rust Programming Language -![rust](https://psiace.github.io/databend-internals/minibend/001-basic-intro/minibend-001-basic-intro_15.png) +![rust](https://databend-internals.psiace.me/minibend/001-basic-intro/minibend-001-basic-intro_15.png) Rust 官方宣传语是:Rust 是一门赋予每个人构建可靠且高效软件能力的语言,现在距离它第一个版本发布也已经过去10年。 @@ -380,7 +380,7 @@ Rust 不完全指南里,从函数、类型、模式匹配、控制流、内存 ### 阅读材料 -![books](https://psiace.github.io/databend-internals/minibend/001-basic-intro/minibend-001-basic-intro_22.png) +![books](https://databend-internals.psiace.me/minibend/001-basic-intro/minibend-001-basic-intro_22.png) 本期课程推荐两本书给大家: diff --git a/docs/content/docs/productivity-topics/databend-rustchinaconf.md b/docs/content/docs/productivity-topics/databend-rustchinaconf.md index 4c1f831..b005c03 100644 --- a/docs/content/docs/productivity-topics/databend-rustchinaconf.md +++ b/docs/content/docs/productivity-topics/databend-rustchinaconf.md @@ -19,7 +19,7 @@ giscus = true ### 什么是 Databend -![what's databend](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_05.png) +![what's databend](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_05.png) 官方的说法是:Databend 是一个使用 Rust 研发、开源、完全面向云架构的新式数仓。 @@ -32,7 +32,7 @@ giscus = true 作为新式数仓,Databend 有哪些基本特性呢? -![databend features](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_06.png) +![databend features](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_06.png) - 首先是弹性:得益于存算分离的架构与设计,Databend 完全可以做到按需、按量弹性扩展。 - 而向量化执行引擎、单指令流多数据流(SIMD)、大规模并行处理(MPP),共同为 Databend 的性能保驾护航。 @@ -46,7 +46,7 @@ giscus = true ### 总览 -![databend arch](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_08.png) +![databend arch](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_08.png) 右边是 Databend 的一个架构图。 @@ -58,7 +58,7 @@ Databend 可以分成 Meta、Computing 和 Storage 三层,也就是元数据 ### 架构与设计 - Meta -![databend arch - meta](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_09.png) +![databend arch - meta](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_09.png) Meta 是一个多租户、高可用的分布式 key-value 存储服务,具备事务能力。 @@ -68,7 +68,7 @@ Meta 是一个多租户、高可用的分布式 key-value 存储服务,具备 ### 架构与设计 - Computing -![databend arch - computing](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_10.png) +![databend arch - computing](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_10.png) 计算层可以由多个集群组成,不同集群可以承担不同的工作负载。每个集群又可以由多个计算节点(node)组成。 @@ -80,7 +80,7 @@ Meta 是一个多租户、高可用的分布式 key-value 存储服务,具备 ### 架构与设计 - Storage -![databend arch - storage](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_11.png) +![databend arch - storage](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_11.png) Databend 使用 Parquet 格式储存数据,为了加快查找(Partition Pruning),Databend 为每个 Parquet 提供了自己的索引:min_max,bloom 。这一部分工作是放在存储层完成的。 @@ -100,7 +100,7 @@ Databend 使用 Parquet 格式储存数据,为了加快查找(Partition Prun 那么,在新的 parser 和 planner 中,Databend 引入了语义检查的环节,在查询编译过程中就可以拦截大部分错误。 -![databend - query check](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_13.png) +![databend - query check](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_13.png) 右图展示的正是两类语义错误,一类是使用了不存在的 Column ,一类是 Column 具有歧义。 @@ -110,7 +110,7 @@ Databend 使用 Parquet 格式储存数据,为了加快查找(Partition Prun 在引入新 Planner 之后,计算层的架构得到进一步的划分,当一个查询请求进来以后,会经过以下处理: -![databend - planner](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_14.png) +![databend - planner](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_14.png) - 基于 nom 定制的解析器会负责生成抽象语法树,值得一提的是,在新 parser 中支持新语句也非常方便。 - Binder 会对语法树进行语义分析,并且生成一个初始的 Logical Plan(逻辑计划)。 @@ -127,7 +127,7 @@ Databend 使用 Parquet 格式储存数据,为了加快查找(Partition Prun Databend 最近正在研发一套全新的表达式框架,其中包含一套形式化的类型系统,算是使用 Rust 自定义类型系统的最佳范例。 -![databend - typed type](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_15.png) +![databend - typed type](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_15.png) 通过引入形式化方法,可以提高设计的可靠性和健壮性。对应到新表达式框架中: @@ -163,7 +163,7 @@ Databend 选择 Rust ,其实有很多原因:极客精神、健壮性等。 参见:[周刊(第7期):一个C系程序员的Rust初体验 - codedump的网络日志](https://www.codedump.info/post/20220227-weekly-7/) -![databend - fast iter](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_17.png) +![databend - fast iter](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_17.png) 这里给大家分享一下 Databend 的快速迭代方法论。 @@ -177,7 +177,7 @@ Databend 选择 Rust ,其实有很多原因:极客精神、健壮性等。 ### 测试风格 -![databend - test style](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_18.png) +![databend - test style](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_18.png) Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图左侧展示的这样,针对性地禁用了 src 目录下的 doctest 和 test 。 @@ -193,7 +193,7 @@ Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图 - [Delete Cargo Integration Tests](https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html) - [Databend 社区如何做测试 [ 虎哥的博客 ] (bohutang.me)](https://bohutang.me/2021/09/14/databend-cloud-warehouse-how-to-test/) -- [如何为 Databend 添加新的测试 | Databend 内幕大揭秘](https://psiace.github.io/databend-internals/docs/contribute-to-databend/write-and-run-tests/) +- [如何为 Databend 添加新的测试 | Databend 内幕大揭秘](https://databend-internals.psiace.me/docs/contribute-to-databend/write-and-run-tests/) ### 代码演进 @@ -201,7 +201,7 @@ Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图 **eg.1** -![databend - code refactor 1](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_19.png) +![databend - code refactor 1](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_19.png) 第一个例子是大家编写异步代码时常用的 async trait ,用起来很方便,就像左上角的例子,但是有一些小缺点: @@ -218,7 +218,7 @@ Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图 **eg.2** -![databend - code refactor 2](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_20.png) +![databend - code refactor 2](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_20.png) 第二个例子是关于分发的,分发其实就是要确定调用接口时是调用哪个实例和它具体的类型。分发的方式不同,其成本也不同。 @@ -237,7 +237,7 @@ Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图 **eg.1** -![databend - bug 1](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_21.png) +![databend - bug 1](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_21.png) 之前,上图中的代码片段没有加环境变量判断,导致程序会默认开启日志发送服务。 @@ -245,7 +245,7 @@ Databend 的单元测试组织形式有别于一般的 Rust 项目,像上图 **eg.2** -![databend - bug 2](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_22.png) +![databend - bug 2](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_22.png) 左图这个代码片段其实 tracing 的文档中已经给了提示。 @@ -286,7 +286,7 @@ Databend 的成长离不开 Rust 社区和开源共同体,Databend 社区也 ### 课程 -![databend - course](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_25.png) +![databend - course](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_25.png) 自 21 年 8 月起,Databend 和 Rust 中文社区、知数堂, 启动了面向 Rust 和数据库开发人员的公开课计划,前后一共输出 34 期课程。 @@ -310,7 +310,7 @@ Databend 是一款云数仓,不仅仅是云原生数仓,更是云上数仓 ### 一站式数据分析云平台 -![databend - cloud](https://psiace.github.io/databend-internals/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_28.png) +![databend - cloud](https://databend-internals.psiace.me/productivity-topics/Databend-RustConfChina2022/Databend-RustConfChina2022_28.png) Databend Cloud 是 Databend 打造的一款易用、低成本、高性能的新一代大数据分析平台,让用户更加专注数据价值的挖掘。 diff --git a/docs/content/docs/productivity-topics/the-databend-way-to-sky.md b/docs/content/docs/productivity-topics/the-databend-way-to-sky.md index f38f80e..bfe7c14 100644 --- a/docs/content/docs/productivity-topics/the-databend-way-to-sky.md +++ b/docs/content/docs/productivity-topics/the-databend-way-to-sky.md @@ -13,7 +13,7 @@ top = false giscus = true +++ -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-01.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-01.png) ## 背景 @@ -21,13 +21,13 @@ giscus = true > 根据 CNCF 对云原生的定义:云原生技术使组织能够在公共、私有和混合云这类现代、动态的环境中构建和运行可扩展的应用程序。典型示例包括:容器、服务网格、微服务、不变基础设施和声明式 API 。 -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-02.jpg) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-02.jpg) 然而,无论是公有云还是私有云、无论是云计算还是云服务,在天空中都已经存在太多不同类型的“云”。每个“云”都拥有自己独特的 API 和生态系统,并且彼此之间缺乏互操作性,能够兼容的地方也是寥寥无几。云已经成为事实上的孤岛。这个孤岛不仅仅是指公有云和私有云之间的隔阂,还包括了不同公有云之间、不同私有云之间、以及公有云和私有云之间的隔阂。这种孤岛现象不仅给用户带来了很多麻烦,也限制了云计算的发展。 2021 年 RISELab 发表了题为 [The Sky Above The Clouds](https://arxiv.org/abs/2205.07147) 的论文,讨论关于天空计算的未来。天空计算将云原生的思想进一步扩展,从而囊括公有云、私有云和边缘设备。其目标是实现一种统一的 API 和生态体系,使得不同云之间可以无缝地协作和交互。这样一来,用户就可以在不同的云之间自由地迁移应用程序和数据,而不必担心兼容性和迁移成本的问题。同时,天空计算还可以提供更高效、更安全、更可靠的计算服务,从而满足用户对于云计算的不断增长的需求。总体上讲,天空计算致力于允许应用跨多个云厂商运行,实现多云之间的互操作性。 -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-03.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-03.png) *(上图引自论文,展示不同类型的多云与天空的区别)* @@ -37,7 +37,7 @@ giscus = true Databend 能够满足用户在不同的云之间自由地访问数据并进行查询,而不必担心兼容性和迁移成本的问题。同时,Databend 还可以提供更高效、更安全、更可靠的计算服务,从而满足用户对于云计算的不断增长的需求。从这个角度来看,Databend 已经初步形成了一套天空计算的解决方案。那么,对 Databend 而言,跨云的关键到底落在哪里呢? -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-04.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-04.png) *(上图所示为 Databend Cloud 架构示意图)* @@ -45,7 +45,7 @@ Databend 采用存算分离的架构,并完全面向云对象存储进行设 Query 节点和 Meta 节点本身都是轻量化的服务,并且对于部署环境没有严格的依赖。但数据的存储和访问管理就不一样,我们需要考虑不同云服务之间的 API 兼容性、以及如何与云服务本身的安全机制交互从而提供更安全的访问控制机制。对于 Databend 而言,跨云,或者说实现天空计算的关键,就落在数据的管理与访问之上。 -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-05.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-05.png) *(OpenDAL 可以将数据访问问题从 M\*N 转化为 M+N)* @@ -65,7 +65,7 @@ bucket = "databend" 当然,仅支持 S3 兼容的对象存储服务还不够。Databend 通过 OpenDAL 实现了 Google Cloud Storage、Azure Blob、Aliyun OSS、Huawei OBS 和 HDFS 等服务的原生存储后端支持。 这意味着 Databend 可以充分利用各种供应商提供的 API,为用户带来更优秀的体验。例如,Aliyun OSS 的原生支持使得 Databend 可以通过 Aliyun RAM 对用户进行认证和授权,无需设置静态密钥,从而大大提高安全性并降低运维负担。 -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-06.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-06.png) *(上图选自阿里云官网,访问控制场景与能力)* @@ -169,7 +169,7 @@ COPY INTO @s2 FROM (SELECT name, age, id FROM test_table LIMIT 100) FILE_FORMAT 为了更好地满足多云环境下的数据库查询需求,Databend 设计并实现了一套 RESTful API 来支持数据共享。 -![](https://psiace.github.io/databend-internals/productivity-topics/sky-computing/databend-sky-computing-07.png) +![](https://databend-internals.psiace.me/productivity-topics/sky-computing/databend-sky-computing-07.png) *(上图所示为数据共享的工作流)* diff --git a/docs/content/docs/source-reading/init-session-handler.md b/docs/content/docs/source-reading/init-session-handler.md index d4560d3..a5727e6 100644 --- a/docs/content/docs/source-reading/init-session-handler.md +++ b/docs/content/docs/source-reading/init-session-handler.md @@ -63,7 +63,7 @@ pub type Singleton = Arc>; 接下来会根据网络协议初始化 handlers,并把它们注册到 `shutdown_handler` 的 services 中,任何实现 `Server` trait 的类型都可以被添加到 services 中。 -![query server](https://psiace.github.io/databend-internals/source-reading/init-session-handler/01-query-server.png) +![query server](https://databend-internals.psiace.me/source-reading/init-session-handler/01-query-server.png) ```rust #[async_trait::async_trait] @@ -162,7 +162,7 @@ pub trait Server: Send { - `query_ctx` :每一条查询语句会有一个 query_ctx,用来存储当前查询的一些上下文信息 。 - `query_ctx_shared` :查询语句中的子查询共享的上下文信息 。 -![session](https://psiace.github.io/databend-internals/source-reading/init-session-handler/02-session.png) +![session](https://databend-internals.psiace.me/source-reading/init-session-handler/02-session.png) 下面逐一来分析。 diff --git a/docs/content/docs/source-reading/intro.md b/docs/content/docs/source-reading/intro.md index a053333..e27396b 100644 --- a/docs/content/docs/source-reading/intro.md +++ b/docs/content/docs/source-reading/intro.md @@ -32,7 +32,7 @@ Databend 在 issue 中还引入了“Good First issue”的 label 来引导社 我们早期的成员大多是 ClickHouse、tidb 、tokudb 等知名数据库的贡献者,从技术栈来说更熟悉的是 C++ 和 Go。虎哥([@bohutang](https://github.com/bohutang))在疫情期间也使用 Go 实现了一个小的数据库原型 [vectorsql](https://github.com/vectorengine/vectorsql),有同学表示 vectorsql 的架构非常优雅,值得学习借鉴。 -![vectorsql](https://psiace.github.io/databend-internals/source-reading/intro/01-vectorsql.png) +![vectorsql](https://databend-internals.psiace.me/source-reading/intro/01-vectorsql.png) 语言本没有孰劣之分,要从面向的场景来聊聊。目前大多的 DMBS 使用的是 C++/Java,新型的 NewSQL 更多使用的是 Go。在以往的开发经验来看,C/C++ 已经是高性能的代名词,开发者更容易写出高运行效率的代码,但 C++ 的开发效率实在不忍直视,工具链不是很完善,开发者很难一次性写出内存安全,并发安全的代码。而 Go 可能是另外一个极端,大道至简,工具链完善,开发效率非常高,不足之处在于泛型的进度太慢了,在 DB 系统上内存不能很灵活的控制,且难于达到前者的运行性能,尤其使用 SIMD 指令还需要和汇编代码交互等。我们需要的是兼具 开发效率(内存安全,并发安全,工具链完善)& 运行效率 的语言,当时看来,Rust 可能是我们唯一的选择了,历经尝试后,我们也发现,Rust 不仅能满足我们的需求,而且很酷! @@ -52,7 +52,7 @@ Databend 在 issue 中还引入了“Good First issue”的 label 来引导社 画虎画皮难画骨,我们先从 Databend 的“骨”聊起。 -![databend arch](https://psiace.github.io/databend-internals/source-reading/intro/02-databend-arch.png) +![databend arch](https://databend-internals.psiace.me/source-reading/intro/02-databend-arch.png) 虽然我们是使用 Rust 从零开始实现的,但不是完全闭门造轮子,一些优秀的开源组件或者生态也有在其中集成。如:我们兼容了 Ansi-SQL 标准,提供了 MySQL/ClickHouse 等主流协议的支持,拥抱了万物互联的 Arrow 生态,存储格式基于大数据主流的 Parquet 格式等。我们不仅会积极地回馈了贡献给上游,如 Arrow2/Tokio 等开源库,一些通用的组件我们也抽成独立的项目开源在Github(openraft, opendal, opencache, opensrv 等)。 @@ -80,7 +80,7 @@ MetaService 主要用于存储读取持久化的元数据信息,比如 Catalog Query 节点主要用于计算,多个 query 节点可以组成 MPP 集群,理论上性能会随着 query 节点数水平扩展。SQL 在 query 中会经历以下几个转换过程: -![query](https://psiace.github.io/databend-internals/source-reading/intro/03-query.png) +![query](https://databend-internals.psiace.me/source-reading/intro/03-query.png) 从 SQL 字符串经过 Parser 解析成 AST 语法树,然后经过 Binder 绑定 catalog 等信息转成逻辑计划,再经过一系列优化器处理转成物理计划,最后遍历物理计划构建对应的执行逻辑。 query 涉及的模块有: diff --git a/docs/content/docs/source-reading/pipeline_model_graph_based.md b/docs/content/docs/source-reading/pipeline_model_graph_based.md index 52fa129..821a73f 100644 --- a/docs/content/docs/source-reading/pipeline_model_graph_based.md +++ b/docs/content/docs/source-reading/pipeline_model_graph_based.md @@ -17,7 +17,7 @@ giscus = true ## 一.基于图的初始化 -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/1-pipeline-arch.png) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/1-pipeline-arch.png) 上图便是 databend 的一条 pipeline 结构,通常对于每一个 PipeItem,这里只会有一个 input_port 和 output_port,一个 Pipe 当中的 PipeItem 的数量则通常代表着并行度.每一个 PipeItem 里面对应着一个算子(不过在有些情况下并不一定一个 pipeItem 就只有一对 input_port 和 output_port,所以上图画的更加广泛一些),算子的推进由调度模型来触发 @@ -25,8 +25,8 @@ giscus = true databend 采取的是采取的是 StableGraph 这个结构,我们最开始是得到了下面第一张图这样的 Pipeline,我们最后生成的是下面第二张图的 graph. -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/2-pipeline-graph-build-01.jpg) -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/3-pipeline-graph-build-02.jpg) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/2-pipeline-graph-build-01.jpg) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/3-pipeline-graph-build-02.jpg) 上面第二张图的的连接只是一个物理上的单纯图的连接,但是 node 内部 pipe_item 对应的 port 没有对接起来.我们还需要关心的是具体如何把对应的 port 给连接起来的.在构建图的时候每一个 PipeItem 包装为一个 node,包装的过程是以 Pipe 为顺序的.这样我们就为上面每一个 PipeItem 都加上了一个 Node 编号,后面我们需要按照为对应的 input_port 和 output_port 去加上 edge,我们的连接是一个平行的连接. @@ -83,7 +83,7 @@ pub struct UpdateTrigger { // 上面的例子最后我们得到的graph初始化后应该是下面这样 ``` -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/4-pipeline-graph-build-03.jpg) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/4-pipeline-graph-build-03.jpg) ```rust // 而对于input_port和output_port的数据的传递,则是两者之间共享一个SharedData @@ -100,7 +100,7 @@ pub struct SharedStatus { 初始化调度是将我们的 graph 的所有出度为 0 的 Node 作为第一次任务调度节点,对应我们的例子就是 Node4,Node5 每一次调度都是抽取出 graph 当中的同步任务和异步任务,下图是 pipeline 的调度模型,用于抽取出当前 graph 当中可执行的同步 processor 和异步 processor,调度模型的输入是最上面的 graph,而输出则是 sync_processor_queue 和 async_processor_queue,无论是在初始化时还是在后面继续执行的过程都是利用的下面的调度模型来进行调度.调度模型的执行终点是 need_schedule_nodes 和 need_schedule_edges 均为空 -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/5-pipeline-model.jpg) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/5-pipeline-model.jpg) ## 三.执行模型 @@ -160,7 +160,7 @@ struct WorkerCondvar { ``` 执行模型的流程图如下: -![](https://psiace.github.io/databend-internals/source-reading/pipeline_model_graph/6-parallel-pipeline-model.jpg) +![](https://databend-internals.psiace.me/source-reading/pipeline_model_graph/6-parallel-pipeline-model.jpg) ## 四. 限时机制 diff --git a/docs/content/docs/the-basics/executor-in-query-process.md b/docs/content/docs/the-basics/executor-in-query-process.md index 6bf166b..db24332 100644 --- a/docs/content/docs/the-basics/executor-in-query-process.md +++ b/docs/content/docs/the-basics/executor-in-query-process.md @@ -17,7 +17,7 @@ giscus = true 首先一起来回顾一下查询的基本流程。 -![Query Steps](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/01-query-steps.png) +![Query Steps](https://databend-internals.psiace.me/the-basics/executor-in-query-process/01-query-steps.png) 如上图所示,查询往往需要经历下述几个阶段: @@ -31,7 +31,7 @@ giscus = true 1990 年发表的 [_Volcano, an Extensible and Parallel Query Evaluation System_](https://dl.acm.org/doi/10.1109/69.273032) 中提出 Volcano Model 并为人熟知。 -![Volcano](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/02-volcano.png) +![Volcano](https://databend-internals.psiace.me/the-basics/executor-in-query-process/02-volcano.png) Volcano 是一种基于行的流式迭代模型,简单而又优美。拉取数据的控制命令从最上层的算符依次传递到执行树的最下层,与数据的流动方向正好相反。 @@ -55,7 +55,7 @@ Volcano 是一种基于行的流式迭代模型,简单而又优美。拉取数 Databend 的执行器部分主要借鉴了 [_Morsel-Driven Parallelism: A NUMA-Aware Query Evaluation Framework for the Many-Core Age_](https://dl.acm.org/doi/10.1145/2588555.2610507) 这篇论文。 -![Morsel-Driven Parallelism](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/03-morsel-driven.png) +![Morsel-Driven Parallelism](https://databend-internals.psiace.me/the-basics/executor-in-query-process/03-morsel-driven.png) ### 面向多核架构 @@ -77,7 +77,7 @@ Morsel-Driven Parallelism 的研究不仅仅关注执行框架的改进,还涵 向量化执行自 MonetDB/X100(Vectorwise)开始流行,[_MonetDB/X100: Hyper-Pipelining Query Execution_](https://www.cidrdb.org/cidr2005/papers/P19.pdf) 这篇论文也成为了必读之作。而在 2010 年之后的 OLAP 系统,基本上都是按列式存储进行数据组织的。 -![Column Based](https://psiace.github.io/databend-internals/the-basics/executor-in-query-process/04-column-based-vectorwise.png) +![Column Based](https://databend-internals.psiace.me/the-basics/executor-in-query-process/04-column-based-vectorwise.png)

左图可以看作列式存储的一个样本,同一列的数据在内存中形成一个连续的结构。

diff --git a/docs/content/docs/the-basics/storage.md b/docs/content/docs/the-basics/storage.md index 962ae37..f6b7c92 100644 --- a/docs/content/docs/the-basics/storage.md +++ b/docs/content/docs/the-basics/storage.md @@ -19,7 +19,7 @@ giscus = true 综合存储介质的性能和成本,大致可以得到一个如下图所示的层次结构: -![Storage Level](https://psiace.github.io/databend-internals/the-basics/storage/01-storage-level.png) +![Storage Level](https://databend-internals.psiace.me/the-basics/storage/01-storage-level.png) **常见存储介质**