六千字嘔心瀝血深度總結,為您揭秘ClickHouse為什么查詢這么快!

1. ClickHouse設計思想和核心技術特征

1.1 ClickHouse 全知全解

ClickHouse 是一個用于聯機分析 (OLAP) 的列式數據庫管理系統 (DBMS)。來自于 2011 年在納斯達克上市的俄羅斯本土搜索引擎企業 Yandex 公司, 誕生之初就是為了服務 Yandex 公司自家的 Web 流量分析產品 Yandex.Metrica,后來經過演變,逐漸形成為現在的 ClickHouse,全稱是:Click Stream, Data WareHouse

ClickHouse 官網:https://clickhouse.tech/,它具有 ROLAP、在線實時查詢、完整的 DBMS 功能支持、列式存儲、不需要任何數據預處理、支持批量更 新、擁有非常完善的 SQL 支持和函數、支持高可用、不依賴 Hadoop 復雜生態、開箱即用等許多特點。

在 1 億數據集體量的情況下,ClickHouse 的平均響應速度是 Vertica 的 2.63 倍、InfiniDB 的 17 倍、MonetDB 的 27 倍、Hive 的 126 倍、MySQL 的 429 倍以及Greenplum 的 10 倍。詳細的測試結果可以查閱:https://clickhouse.tech/benchmark/dbms/

ClickHouse 非常適用于商業智能領域(也就是我們所說的 BI 領域),除此之外,它也能夠被廣泛應用于廣告流量、Web、App 流量、電信、金融、電子 商務、信息安全、網絡游戲、物聯網等眾多其他領域。

ClickHouse 是近年來備受關注的開源列式數據庫,主要用于數據分析(OLAP)領域。目前國內社區火熱,各個大廠紛紛跟進大規模使用:

  • 今日頭條內部用 ClickHouse 來做用戶行為分析,內部一共幾千個 ClickHouse 節點,單集群最大 1200 節點,總數據量幾十 PB,日增原始數據 300TB 左右。
  • 騰訊內部用 ClickHouse 做游戲數據分析,并且為之建立了一整套監控運維體系。
  • 攜程內部從 18 年 7 月份開始接入試用,目前 80% 的業務都跑在 ClickHouse 上。每天數據增量十多億,近百萬次查詢請求。
  • 快手內部也在使用 ClickHouse,存儲總量大約 10PB, 每天新增 200TB, 90% 查詢小于 3S。

ClickHouse 缺點:

  1. 沒有完整的事務支持;
  2. 稀疏索引導致 ClickHouse 不擅長細粒度或者 key-value 類型數據的查詢需求;
  3. 缺少高頻率,低延遲的修改或刪除已存在數據的能力。僅能用于批量刪除或修改數據 ;
  4. 不擅長 join 操作;

1.2 ClickHouse 設計思路剖析

那么一個專門用來做 OLAP 分析的存儲引擎該如何設計呢?

如何在海量數據中,針對大量數據進行查詢分析呢?核心需求是 實現海量數據集中的高性能低延遲查詢分析功能,一些常見的方案和手段如下:

  1. 數據排序
  2. 數據分區分片 + 分布式查詢
  3. 列式存儲 + 字段類型統一
  4. 列裁剪
  5. 預聚合(搜索引擎: 輸入關鍵詞,搜索引擎根據關鍵詞到 數據庫 找到這個 關鍵詞對應的所有的 URL:這些 URL 就是提前計算出來的 )
  6. 利用CPU特性:向量化引擎,操作系統必須支持;
  7. 主鍵索引 + 二級索引 + 位圖索引 + 布隆索引 等等各種索引技術
  8. 支持近似計算, pv 一個電商平臺的 sku 總數;
  9. 定制引擎:多樣化的存儲引擎滿足不同場景的特定需要;
  10. 多樣化算法選擇:Volnitsky高效字符串搜索算法 和 HyperLogLog基于概率高效去重算法;

總結一下:單條記錄的增刪改查操作,通過數據橫向切割,做到數據操作的快速定位,在海量數據分析中,一般就是針對大量行數據少列做分析,既然并不是全部列,那么把數據做縱向切分把表中的數據按照列來單獨存儲,那么在做分析的時候,同樣可以快速把待查詢分析的數據總量降低到原來表的 1/n,同樣提高效率。而且對于常用的聚合邏輯的結果,也可以提前算出來緩存起來用來提供效率,這就是預聚合技術。

提到預聚合,大家會想到 Kylin, Kylin 是一個把預聚合技術發揮到極致的一個 OLAP 技術,但是 Kylin 也有它的缺點:

  1. 預聚合只支持固定的分析場景,無法滿足自定義分析場景,所以預聚合只能作為一種可選方案 ;
  2. 維度組合爆炸會導致數據膨脹,這樣會造成不必要的計算和存儲開銷。無必要的維度組合的計算就屬于浪費資源 ;
  3. 大概率數據都是增量生成,預聚合不能進行數據更新。所以會產生大量的重算。

2 ClickHouse 引擎詳解

ClickHouse 是一個 OLAP 類型的分析型數據庫,也有庫和表的概念,而且庫和表還都提供了不同類型的引擎。所以關于 ClickHouse 的底層引擎,其實可以分為 數據庫引擎表引擎 兩種。在此,我們重點講解表引擎。

2.1 ClickHouse 庫引擎介紹

關于庫引擎,簡單總結一下。ClickHouse 也支持在創建庫的時候,指定庫引擎,目前支持 5 種,分別是:Ordinary,Dictionary, Memory, Lazy, MySQL,其實 Ordinary 是默認庫引擎,在此類型庫引擎下,可以使用任意類型的表引擎。

  1. Ordinary引擎: 默認引擎,如果不指定數據庫引擎創建的就是 Ordinary 數據庫;

  2. Dictionary引擎: 此數據庫會自動為所有數據字典創建表 ;

  3. Memory引擎: 所有數據只會保存在內存中,服務重啟數據消失,該數據庫引擎只能夠創建 Memory 引擎表 ;

  4. MySQL引擎: 改引擎會自動拉取遠端 MySQL 中的數據,并在該庫下創建 MySQL 表引擎的數據表;

  5. Lazy延時引擎: 在距最近一次訪問間隔 expiration_time_in_seconds 時間段內,將表保存在內存中,僅適用于 Log 引擎表;

2.2 ClickHouse 表引擎介紹

表引擎在 ClickHouse 中的作用十分關鍵,直接決定了數據如何存儲和讀取、是否支持并發讀寫、是否支持 index、支持的 query 種類、是否支持主備復制等。

  1. 數據的存儲方式和位置,寫到哪里以及從哪里讀取數據
  2. 支持哪些查詢以及如何支持。
  3. 并發數據訪問。
  4. 索引的使用(如果存在)。
  5. 是否可以執行多線程請求。
  6. 數據復制參數。

具體可看官網:https://clickhouse.tech/docs/zh/engines/table-engines/

ClickHouse 的表引擎提供了四個系列(Log、MergeTree、Integration、Special)大約 28 種表引擎,各有各的用途。比如 Log 系列用來做小表數據分 析,MergeTree 系列用來做大數據量分析,而 Integration 系列則多用于外表數據集成。Log、Special、Integration 系列的表引擎相對來說,應用場景有限,功能簡單,應用特殊用途,MergeTree 系列表引擎又和兩種特殊表引擎(Replicated,Distributed)正交形成多種具備不同功能的 MergeTree 表引擎。

image.png

MergeTree 作為家族中最基礎的表引擎,提供了主鍵索引、數據分區、數據副本和數據采樣等基本能力,而家族中其他的表引擎則在 MergeTree 的基礎 之上各有所長:

image.png

2.3 MergeTree 引擎工作機制詳解

MergeTree 系列是官方主推的存儲引擎,支持幾乎所有 ClickHouse 核心功能,該系列中,常用的表引擎有:MergeTreeReplacingMergeTreeCollapsingMergeTreeVersionedCollapsingMergeTreeSummingMergeTreeAggregatingMergeTree 等。學習好 MergeTree 表引擎的工作機 制,是應用好 ClickHouse 的最基本基礎。

關于 MergeTree 表引擎類型:

  • 原生 MergeTree 表引擎主要用于海量數據分析,支持數據分區、存儲有序、主鍵索引、稀疏索引、數據 TTL 等。MergeTree 支持所有ClickHouse SQL 語法,但是有些功能與 MySQL 并不一致,比如在 MergeTree 中主鍵并不用于去重。
  • 為了解決 MergeTree 相同主鍵無法去重的問題,ClickHouse 提供了 ReplacingMergeTree 引擎,用來做去重。ReplacingMergeTree 確保數據最終被去重,但是無法保證查詢過程中主鍵不重復。因為相同主鍵的數據可能被 shard 到不同的節點,但是 compaction 只能在一個節點中進行,而且 optimize 的時機也不確定。
  • 解決刪除場景,CollapsingMergeTree 引擎要求在建表語句中指定一個標記列 Sign(插入的時候指定為 1,刪除的時候指定為 -1),后臺 Compaction 時會將主鍵相同、Sign 相反的行進行折疊,也即刪除。來消除 ReplacingMergeTree 的限制。
  • 為了解決 CollapsingMergeTree 亂序寫入情況下無法正常折疊問題,VersionedCollapsingMergeTree 表引擎在建表語句中新增了一 列 Version,用于在亂序情況下記錄狀態行與取消行的對應關系。主鍵相同,且 Version 相同、Sign 相反的行,在 Compaction 時會被刪除。
  • 解決聚合場景,ClickHouse 通過 SummingMergeTree 來支持對主鍵列進行預先聚合。在后臺 Compaction 時,會將主鍵相同的多行進行 sum 求 和,然后使用一行數據取而代之,從而大幅度降低存儲空間占用,提升聚合計算性能。同理還有 AggregatingMergeTree用來預聚合平均值。

MergeTree 的建表語法:

CREATE TABLE [IF NOT EXISTS] [db_name.]table_name ( name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr], name2 [type] [DEFAUErEMAMLERLALLIZED|ALIAS expr], 省略...
) ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, 省略...]

介紹一下其中的幾個關鍵選項:

  1. PARTITION BY: 分區鍵。指定表數據以何種標準進行分區。分區鍵既可以是單個列字段,也可以通過元組的形式使用多個列字段,同時它也支持使用列表達 式。選填。如果沒有執行分區字段,則所有數據,都在一個分區里面: all;
  2. ORDER BY: 排序鍵,用于指定在一個數據片段內,數據以何種標準排序。默認情況下主鍵(PRIMARY KEY)與排序鍵相同。必填。
  3. PRIMARY KEY: 主鍵。聲明后會依照主鍵字段生成一級索引。默認情況下,主鍵與排序鍵(ORDER BY)相同,所以通常直接使用 ORDER BY 代為指定主鍵。
  4. SETTINGS: index_granularity 選項表示索引的粒度,默認值為 8192。MergeTree 索引在默認情況下,每間隔 8192 行數據才生成一條索引。選填。
  5. SAMPLE BY:抽樣表達式,用于聲明數據以何種標準進行采樣。選填。

注意 settings 中的重要參數:

  1. index_granularity 默認是 8192 = 1024 * 8, 推薦不修改
  2. index_granularity_bytes 默認 10M,需要通過 enable_mixed_granularity_parts 來開啟
  3. enable_mixed_granularity_parts 默認開啟自適應索引粒度
  4. merge_with_ttl_timeout 提供數據 TTL 功能;

這里要特別聲明,MergeTree 主鍵索引是稀疏索引!

  • 稠密索引: 一條數據創建一條索引;
  • 稀疏索引: 一段數據創建一條索引;

3. ClickHouse 工作原理

本章節將會介紹 MergeTree 表引擎的內部工作細節! 最終就是告訴大家為什么clickhouse做查詢分析那么快?

ClickHouse 從 OLAP 場景需求出發,定制開發了一套全新的高效列式存儲引擎,并且實現了數據有序存儲、主鍵索引、稀疏索引、數據 Sharding、數據 Partitioning、TTL、主備復制等豐富功能。這些功能共同為 ClickHouse 極速的分析性能奠定了基礎。

  • clickhouse 數據分區
  • clickhouse 列式存儲
  • clickhouse 一級索引 主鍵索引
  • clickhouse 二級索引 跳數索引
  • clickhouse 數據壓縮
  • clickhouse 數據標記

3.1 數據分區

關于表分區目錄結構: MergeTree 表的分區目錄物理結構,該表有 a,b,date,name 四個字段。 當創建好了這張表之后,那么一次批量插入,就可能形成多個分區,其實每個分區,就是表存儲目錄中的一個子文件夾

假設用一個 文件夾來存儲這張表的所有數據,為了提高效率,可以考慮把 表的所有數據,按照某個維度,分割成多個子文件夾,假設以日期字段為例, 查詢不同的月份,到表文件夾的不同子文件夾中尋找即可。

引出兩個問題:

  • 分區文件夾的命名規則是什么?合并規則是什么?
  • 分區文件夾的文件列表,各是什么作用,什么含義?
image.png

關于這些文件的解釋:

  1. 分區目錄:20190710_20190711_1_5_1,一個分區可能會有多個不同的目錄,該目錄下存儲該分區的數據及其他各種形式的數據。后臺會執行合并,把相同分 區的多個目錄合并到一個分區。
  2. checksums.txt:校驗文件。使用二進制格式存儲。它保存了余下各類文件(primary.idx、count.txt等)的 size 大小及 size 的哈希值,用于快速校 驗文件的完整性和正確性。
  3. columns.txt:列信息文件,使用明文格式存儲。用于保存此數據分區下的列字段信息 。
  4. count.txt:計數文件,使用明文格式存儲。用于記錄當前數據分區目錄下數據的總行數。
  5. primary.idx:一級索引文件,主鍵索引文件。
  6. xxx.bin:數據文件,使用壓縮格式存儲,默認為 LZ4 壓縮格式,用于存儲某一列的數據,每一列都對應一個該文件,如列 date 為 date.bin。
  7. xxx.mrk:列字段標記文件。
  8. xxx.mrk2:列字段標記文件,如果使用了自適應大小的索引間隔,則標記文件以 .mrk2 命名,否則以 .mrk 命名。它建立 primary.idx 稀疏索引與 xxx.bin 數據文件之間的映射關系,先通過主鍵索引找到數據的偏移量,然后去 xxx.bin 數據文件中找到真實數據
  9. 還有二級索引 和 分區鍵相關信息文件,跳數索引文件等等

關于表分區命名規則:分區的命名規則:PartitionID_MinBlockNum_MaxBlockNum_Level

image.png

該 blocknum 在該表內全局累加,每次創建一個新的分區目錄的時候,就會累加 1。Level 是分區被合并過的次數計數,合并一次則加1。

insert into table values(201905 zhangsan), (201906  lisi), (201906  wangwu);            201905_1_1_0     201906_2_2_0
insert into table values(201905 zhangsan), (201906  lisi), (201906  wangwu);            201905_3_3_0     201906_4_4_0
201905_1_1_0 + 201905_3_3_0 = 201905_1_3_1
201905_3_5_2 + 201905_6_9_3 = 201905_3_9_4

關于分區的合并規則:

image.png

3.2 列式存儲

對于 OLAP 技術來說,一般都是這對大量行少量列做聚合分析,所以列式存儲技術基本可以說是 OLAP 必用的技術方案。列式存儲相比于行式存儲,列式存儲在分析場景下有著許多優良的特性。

  • 分析場景中往往需要讀大量行但是少數幾個列。在行存模式下,數據按行連續存儲,所有列的數據都存儲在一個block中,不參與計算的列在IO時也 要全部讀出,讀取操作被嚴重放大。而列存模式下,只需要讀取參與計算的列即可,極大的減低了IO cost,加速了查詢。
  • 同一列中的數據屬于同一類型,壓縮效果顯著,壓縮比高。列存往往有著高達十倍甚至更高的壓縮比,節省了大量的存儲空間,降低了存儲成本。
  • 更高的壓縮比意味著更小的data size,從磁盤中讀取相應數據耗時更短。
  • 自由的壓縮算法選擇。不同列的數據具有不同的數據類型,適用的壓縮算法也就不盡相同。可以針對不同列類型,選擇最合適的壓縮算法。
  • 高壓縮比,意味著同等大小的內存能夠存放更多數據,系統cache效果更好。
image.png

3.3 一級索引

關于一級索引: MergeTree 的主鍵使用 PRIMARY KEY 定義,待主鍵定義之后,MergeTree 會依據index_granularity 間隔(默認 8192 行),為數 據表生成一級索引并保存至 primary.idx 文件內。一級索引是稀疏索引,意思就是說:每一段數據生成一條索引記錄,而不是每一條數據都生成索引, 如果是每一條數據都生成索引,則是稠密索引。稀疏索引的好處,就是少量的索引標記,就能記錄大量的數據區間位置信息,比如不到 24414 條標記信 息,就能為 2E 條數據提供索引(算法:200000000 / 8192)。在 ClickHouse 中,一級索引常駐內存。總的來說: 一級索引和標記文件一一對齊,兩個 索引標記之間的數據,就是一個數據區間,在數據文件中,這個數據區間的所有數據,生成一個壓縮數據塊。

image.png

需要注意的是: ClickHouse 的主鍵索引與 MySQL 等數據庫不同,它并不用于去重,即便 primary key 相同的行,也可以同時存在于數據庫中。要想實現去重效果,需要結合具體的表引擎 ReplacingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree 實現。這個在之前的表引擎介紹中講過。

3.4 二級索引

關于二級索引: 又稱之為跳數索引。目的和一級索引一樣,是為了減少待搜尋的數據的范圍。跳數索引的默認是關閉的,需要通過參數來開啟,索引生成粒度由 granularity 控制,如果生成了二級索引,則會在分區目錄下生成額外的:skp_idx_[Column].idxskp_idx_[Column].mrk 文件。跳數索引的生成規則:按照特定規則每隔 granularity 個 index_granularity 條數據,就會 生成一條跳數索引。比如 minmax 跳數索引,生成的是:granularity 個 index_granularity 條數據內的最大值最小值生成一條索引,如果將來需要針對 構建二級索引的這個字段求最大值最小值,則可以幫助提高效率。跳數索引一共支持四種類型:minmax(最大最小)、set(去重集合)、 ngrambf_v1(ngram 分詞布隆索引) 和 tokenbf_v1(標點符號分詞布隆索引),一張數據表支持同時聲明多個跳數索引。比如:

GRANULARITY = 你在創建二級索引索引的指定的

INDEX_GRANULARITY = 8192 構建一條主鍵索引

GRANULARITY * INDEX_GRANULARITY 構建一條 二級索引

CREATE TABLE skip_test(
    ID String,
    URL String,
    Code String,
    EventTime Date,
    INDEX a ID TYPE minmax GRANULARITY 5,
    INDEX b (length(ID) * 8) TYPE set(2) GRANULARITY 5,
    INDEX c (ID, Code) TYPE ngrambf_v1(3, 256, 2, O) GRANULARITY 5,
    INDEX d ID TYPE tokenbf_v1(256, 2, 0) GRANULARITY 5
) ENGINE= MergeTree()
    order by id;

關于跳數索引支持的多種類型的區別:

  1. minmax:以 index_granularity 為單位,存儲指定表達式計算后的 min、max 值;在等值和范圍查詢中能夠幫助快速跳過不滿足要求的塊,減少 IO。
  2. set(max_rows):以 index granularity 為單位,存儲指定表達式的 distinct value 集合,用于快速判斷等值查詢是否命中該塊,減少 IO。
  3. ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):將 string 進行 ngram 分詞后,構建 bloom filter,能夠優化 等值、like、in 等查詢條件.
  4. tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):與 ngrambf_v1 類似,區別是不使用 ngram 進行分詞,而是通過標點符號進行詞語分割。
  5. bloom_filter([false_positive]):對指定列構建 bloom filter,用于加速 等值、like、in 等查詢條件的執行。
image.png

3.5 數據壓縮

關于數據壓縮: ClickHouse 的數據存儲文件 column.bin 中存儲是一列的數據,由于一列是相同類型的數據,所以方便高效壓縮。在進行壓縮的時候,請 注意:一個壓縮數據塊由頭信息和壓縮數據兩部分組成,頭信息固定使用 9 位字節表示,具體由 1 個 UInt8(1字節)整型和 2 個 UInt32(4字節)整型 組成,分別代表使用的壓縮算法類型、壓縮后的數據大小和壓縮前的數據大小。每個壓縮數據塊的體積,按照其壓縮前的數據字節大小,都被嚴格控制在 64KB~1MB,其上下限分別由 min_compress_block_size(默認65536=64KB)與 max_compress_block_size(默認1048576=1M)參數指定。具體壓 縮規則:

原理的說法: 每 8192 條記錄,其實就是一條一級索引、一個索引區間壓縮成一個數據塊。

1、單個批次數據 size < 64KB:如果單個批次數據小于 64KB,則繼續獲取下一批數據,直至累積到size >= 64KB時,生成下一個壓縮數據塊。如果平均每條 記錄小于8byte,多個數據批次壓縮成一個數據塊

2、單個批次數據 64KB <= size <=1MB:如果單個批次數據大小恰好在 64KB 與 1MB 之間,則直接生成下一個壓縮數據塊。

3、單個批次數據 size > 1MB:如果單個批次數據直接超過 1MB,則首先按照 1MB 大小截斷并生成下一個壓縮數據塊。剩余數據繼續依照上述規則執行。此時, 會出現一個批次數據生成多個壓縮數據塊的情況。如果平均每條記錄的大小超過 128byte,則會把當前這一個批次的數據壓縮成多個數據塊。

image.png

總結:

  • 在一個 xxx.bin 字段存儲文件中,并不是一個壓縮塊對應到一條一級索引,而是每 8192 條數據,構建一條一級索引。
  • 一個 [Column].bin 其實是由一個個的壓縮數據塊組成的。每個壓縮塊的大小在: 64kb - 1M 之間。

注意:一個壓縮數據塊由頭信息和壓縮數據兩部分組成。頭信息固定使用9位字節表示,具體由1個UInt8(1字節)整型和 2 個 UInt32(4字節)整型組成,分別代表使用的壓縮算法類型、壓縮后的數據大小和壓縮前的數據大小;

我們來看看 column.bin 數據文件的組成:

image.png

3.6 數據標記

關于數據標記:數據標記文件也與 .bin 文件一一對應,一級索引和數據之間的橋梁。即每一個列字段 [Column].bin 文件都有一個與之對應的 [Column].mrk2 數據標記文件,用于記錄數據在 .bin 文件中的偏移量信息。一行標記數據使用一個元組表示,元組內包含兩個整型數值的偏移量信息。 它們分別表示在此段數據區間內,在對應的 .bin 壓縮文件中,壓縮數據塊的起始偏移量;以及將該數據壓縮塊解壓后,其未壓縮數據的起始偏移量。每 一行標記數據都表示了一個片段的數據(默認8192行)在 .bin 壓縮文件中的讀取位置信息。標記數據與一級索引數據不同,它并不能常駐內存,而是使 用 LRU(最近最少使用)緩存策略加快其取用速度。

總結數據讀取流程: 先根據一級索引,找到標記文件中的對應數據壓縮塊信息(壓縮塊在 .bin 文件中的起始偏移量和未壓縮之前該條數據的是偏移量) 然后從 .bin 文件中,把壓縮塊加載到內存,解壓縮之后,執行讀取。

數據標記文件也與 .bin 文件一一對應。即每一個列字段 [Column].bin 文件都有一個與之對應的 [Column].mrk 數據標記文件,用于記錄數據在 .bin 文 件中的偏移量信息。

標記文件的最重要的作用,就是建立了主鍵索引到數據文件的數據的映射! MergeTree 具體是如何定位壓縮數據塊并讀取數據的呢?

  • 第一步:根據標記文件中的信息,找到對應的壓縮數據塊,讀取壓縮數據塊,執行解壓縮;
  • 第二步:從解壓縮的數據塊中,以 index_granularity 的粒度加載數據到內存中,執行查詢,直至找到結果數據;

4 ClickHouse 核心查詢流程

數據查詢的本質,可以看作一個不斷減小數據范圍的過程。在最理想的情況下,MergeTree 首先可以依次借助分區索引、一級索引和二級索引,將數據 掃描范圍縮至最小。然后再借助數據標記,將需要解壓與計算的數據范圍縮至最小。

select name from student where date = 201905;
image.png
  1. 指定分區
  2. 指定字段(xxx.bin )
  3. 根據一級索引(primary.idx)定位到 標記文件 (name.mrk2) 中的那一條記錄
  4. 掃描對應字段的 mark 標記文件 獲取兩個偏移量信息(當前要查找的數據,處于這個 .bin 數據文件中的那個 壓縮數據塊,這個壓縮數據塊在 .bin 文件的偏移量, 這個壓縮數據塊解壓縮出來之后,要找的數據在當前這個壓縮數據塊的偏移量)
  5. 根據第一個偏移量去 .bin 文件中定位到一個 壓縮數據快
  6. 讀取數據到內存執行解壓縮
  7. 根據第二個偏移量去內存解壓縮數據中找到對應的數據

提高數據查詢效率的核心原則只有一個: 誰做的輔助動作能快速的幫助我們去快速降低待搜尋的數據范圍
分布式系統的核心思想: 分而治之,必須提供一套架構方便用戶的請求被快速的定位到某個單臺服務器去處理。一般來說,這個服務器處理這個請求,都是很快的!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容