日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ClickHouse 数据存储原理:MergeTree引擎

發布時間:2024/4/11 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ClickHouse 数据存储原理:MergeTree引擎 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • MergeTree引擎
    • 存儲結構
    • 一級索引
      • 稀疏索引
      • 索引粒度index_granularity
      • 索引的查詢過程
      • 聯合主鍵
    • 二級索引
      • 跳數索引
      • granularity
    • 數據標記
      • 生成規則
      • 工作方式
      • 數據標記與壓縮數據塊的對應關系
    • 工作流程
      • 存儲流程
      • 查詢流程


MergeTree引擎

存儲結構

MergeTree的存儲結構


  • partition分區目錄,余下各類數據文件(primary.idx、[Column].mrk、[Column]. bin等)都是以分區目錄的形式被組織存放的,屬于相同分區的數據,最終會被合并到同一個分區目錄,而不同分區的數據,永遠不會被合并在一起。
  • checksums校驗文件,使用二進制格式存儲。它保存了余下各類文件(primary. idx、count.txt等)的size大小及size的哈希值,用于快速校驗文件的完整性和正確性。
  • columns.txt列信息文件,使用明文格式存儲,用于保存此數據分區下的列字段信息。
  • count.txt計數文件,使用明文格式存儲,用于記錄當前數據分區目錄下數據的總行數。
  • primary.idx一級索引文件,使用二進制格式存儲。用于存放稀疏索引,一張MergeTree表只能聲明一次一級索引。借助稀疏索引,在數據查詢的時能夠排除主鍵條件范圍之外的數據文件,從而有效減少數據掃描范圍,加速查詢速度。
  • [Column].bin數據文件,使用壓縮格式存儲,用于存儲某一列的數據。由于MergeTree采用列式存儲,所以每一個列字段都擁有獨立的.bin數據文件,并以列字段名稱命名。
  • [Column].mrk使用二進制格式存儲。標記文件中保存了.bin文件中數據的偏移量信息。標記文件與稀疏索引對齊,又與.bin文件一一對應,所以MergeTree通過標記文件建立了primary.idx稀疏索引與.bin數據文件之間的映射關系。即首先通過稀疏索引(primary.idx)找到對應數據的偏移量信息(.mrk),再通過偏移量直接從.bin文件中讀取數據。由于.mrk標記文件與.bin文件一一對應,所以MergeTree中的每個列字段都會擁有與其對應的.mrk標記文件
  • [Column].mrk2:如果使用了自適應大小的索引間隔,則標記文件會以.mrk2命名。它的工作原理和作用與.mrk標記文件相同。
  • partition.dat與minmax_[Column].idx:如果使用了分區鍵,例如PARTITION BY EventTime,則會額外生成partition.dat與minmax索引文件,它們均使用二進制格式存儲。partition.dat用于保存當前分區下分區表達式最終生成的值;而minmax索引用于記錄當前分區下分區字段對應原始數據的最小和最大值。
  • skp_idx_[Column].idx與skp_idx_[Column].mrk:如果在建表語句中聲明了二級索引,則會額外生成相應的二級索引與標記文件,它們同樣也使用二進制存儲。二級索引在ClickHouse中又稱跳數索引。

一級索引

稀疏索引

當我們定義主鍵之后,MergeTree會依據index_granularity間隔(默認8192行),為數據表生成一級索引并保存至primary.idx文件內,索引數據按照主鍵排序。相比使用主鍵定義,更為常見的簡化形式是通過ORDER BY指代主鍵。在此種情形下,主鍵與ORDER BY定義相同,所以索引(primary.idx)和數據(.bin)會按照完全相同的規則排序。

一級索引底層采用了稀疏索引來實現,從下圖我們可以看出它和稠密索引的區別。

稀疏索引與稠密索引的對比


對于稠密索引而言,每一行索引標記都會對應到具體的一行記錄上。而在稀疏索引中,每一行索引標記對應的一大段數據,而不是具體的一行(他們之間的區別就有點類似mysql中innodb的聚集索引與非聚集索引)。

稀疏索引的優勢是顯而易見的,它只需要使用少量的索引標記就能夠記錄大量數據的區間位置信息,并且數據量越大優勢愈發明顯。例如我們使用默認的索引粒度(8192)時,MergeTree只需要12208行索引標記就能為1億行數據記錄提供索引。由于稀疏索引占用空間小,所以primary.idx內的索引數據能夠常駐內存,取用速度自然極快。


索引粒度index_granularity

索引粒度就如同標尺一般,會丈量整個數據的長度,并依照刻度對數據進行標注,最終將數據標記成多個間隔的小段。數據以index_granularity的粒度(老版本默認8192,新版本實現了自適應粒度)被標記成多個小的區間,其中每個區間最多8192行數據,MergeTree使用MarkRange表示一個具體的區間,并通過startend表示其具體的范圍。

如下圖所示。

MergeTree的存儲結構

index_granularity的命名雖然取了索引二字,但它不單只作用于一級索引(.idx),同時也會影響數據標記(.mrk)和數據文件(.bin)。因為僅有一級索引自身是無法完成查詢工作的,它需要借助數據標記才能定位數據,所以一級索引和數據標記的間隔粒度相同(同為index_granularity行),彼此對齊。而數據文件也會依照index_granularity的間隔粒度生成壓縮數據塊。


索引的查詢過程

索引查詢其實就是兩個數值區間的交集判斷。其中,一個區間是由基于主鍵的查詢條件轉換而來的條件區間;而另一個區間是剛才所講述的與MarkRange對應的數值區間。

整個索引的查詢過程可以分為三大步驟

  • 生成查詢條件區間:將查詢條件轉換為條件區間。即便是單個值的查詢條件,也會被轉換成區間的形式。

    • --舉例-- WHERE ID = 'A000' = ['A000', 'A000']WHERE ID > 'A000' = ('A000', '+inf')WHERE ID < 'A000' = ('-inf', 'A000')WHERE ID LIKE 'A000%' = ['A000', 'A001')
  • 遞歸交集判斷:以遞歸的形式,依次對MarkRange的數值區間與條件區間做交集判斷。從最大的區間[A000 , +inf)開始。

    • 如果不存在交集,則直接通過剪枝算法優化此整段MarkRange
    • 如果存在交集,且MarkRange步長大于N,則將這個區間進一步拆分為N個子區間,并重復此規則,繼續做遞歸交集判斷(N由merge_tree_coarse_index_granularity指定,默認值為8)
    • 如果存在交集,且MarkRange不可再分解,則記錄MarkRange并返回
  • 合并MarkRange區間:將最終匹配的MarkRange聚在一起,合并它們的范圍。

  • 索引查詢全流程

    MergeTree通過遞歸的形式持續向下拆分區間,最終將MarkRange定位到最細的粒度,以幫助在后續讀取數據的時候,能夠最小化掃描數據的范圍。


    聯合主鍵

    當我們以需要以多個字段為主鍵時,此時數據的查詢和存儲就涉及到另外一種規則。

    例如以 (CounterID, Date) 以主鍵,片段中數據首先按 CounterID 排序,具有相同 CounterID 的部分按 Date 排序。排序好的索引的圖示會是下面這樣:

    全部數據 : [-------------------------------------------------------------------------] CounterID: [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiikllllllll] Date: [1111111222222233331233211111222222333211111112122222223111112223311122333] 標記: | | | | | | | | | | |a,1 a,2 a,3 b,3 e,2 e,3 g,1 h,2 i,1 i,3 l,3 標記號: 0 1 2 3 4 5 6 7 8 9 10

    如果指定查詢如下:

    • CounterID in ('a', 'h'),服務器會讀取標記號在 [0, 3) 和 [6, 8) 區間中的數據。
    • CounterID IN ('a', 'h') AND Date = 3,服務器會讀取標記號在 [1, 3) 和 [7, 8) 區間中的數據。
    • Date = 3,服務器會讀取標記號在 [1, 10] 區間中的數據。

    上面例子可以看出使用索引通常會比全表描述要高效。

    • 稀疏索引會引起額外的數據讀取。當讀取主鍵單個區間范圍的數據時,每個數據塊中最多會多讀 index_granularity * 2 行額外的數據。
    • 稀疏索引使得你可以處理極大量的行,因為大多數情況下,這些索引常駐與內存(RAM)中。

    從上面可以看出,ClickHouse的聯合主鍵在某種程度上與我們熟知的最左前綴規則有點類似,通常在以下幾種場景下我們才會考慮使用聯合索引

    • 查詢會使用 b 列作為條件
    • 很長的數據范圍( index_granularity 的數倍)里 a 都是相同的值,并且這樣的情況很普遍。換言之,就是加入另一列后,可以讓你的查詢略過很長的數據范圍。
    • 數據量大,需要改善數據壓縮(以主鍵排序片段數據,數據的一致性越高,壓縮越好)

    長的主鍵會對插入性能和內存消耗有負面影響,但主鍵中額外的列并不影響 SELECT 查詢的性能。


    二級索引

    除了一級索引之外,MergeTree同樣支持二級索引。二級索引又稱跳數索引,由數據的聚合信息構建而成。根據索引類型的不同,其聚合信息的內容也不同。跳數索引的目的與一級索引一樣,也是幫助查詢時減少數據掃描的范圍。

    (二級索引目前還處于測試階段,官方不建議大量使用)

    跳數索引

    目前,MergeTree共支持4種跳數索引,分別是minmax(最值)、set(集合行數)、ngrambf_v1(N-Gram布隆過濾器)和tokenbf_v1(Token布隆過濾器)。一張數據表支持同時聲明多個跳數索引。

    • minmax(最值索引):minmax索引記錄了一段數據內的最小和最大極值,其索引的作用類似分區目錄的minmax索引,能夠快速跳過無用的數據區間。

      • 示例:INDEX [index_name] [column] TYPE minmax GRANULARITY [GRANULARITY SIZE]
    • set(集合行數索引):set索引直接記錄了聲明字段或表達式的不重復值,用于檢測數據塊是否滿足WHERE條件。

      • 示例:INDEX [index_name] [column] TYPE set(max_rows) GRANULARITY [index_granularity]-- max_rows是一個閾值,表示在一個index_granularity內,索引最多記錄的數據行數。(如果max_rows=0,則表示無限制)
    • ngrambf_v1(N-Gram布隆過濾器):ngrambf_v1索引記錄的是指定長度的數據短語的布隆表過濾器,只支持String和FixedString數據類型,同時只能夠提升in、notIn、like、equals和notEquals查詢的性能。

      • 示例:INDEX [index_name] [column] TYPE ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed) GRANULARITY [index_granularity]/* n:token長度,依據n的長度將數據切割為token短語。 size_of_bloom_filter_in_bytes:布隆過濾器的大小。 number_of_hash_functions:布隆過濾器中使用Hash函數的個數。 random_seed: Hash函數的隨機種子。 */
      • 布隆過濾器可能會包含不符合條件的匹配,所以 ngrambf_v1, tokenbf_v1 和 bloom_filter 索引不能用于負向的函數,例如:--可以用來優化的場景 s LIKE '%test%' NOT s NOT LIKE '%test%' s = 1 NOT s != 1 startsWith(s, 'test') i --不能用來優化的場景 NOT s LIKE '%test%' s NOT LIKE '%test%' NOT s = 1 s != 1 NOT startsWith(s, 'test')
    • tokenbf_v1(Token布隆過濾器):tokenbf_v1索引是ngrambf_v1的變種,同樣也是一種布隆過濾器索引。tokenbf_v1除了短語token的處理方法外,其他與ngrambf_v1是完全一樣的。tokenbf_v1會自動按照非字符的、數字的字符串分割token。

      • 示例:INDEX d ID TYPE tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)


    granularity

    對于跳數索引而言,index_granularity定義了數據的粒度,而granularity定義了聚合信息匯總的粒度。換言之,granularity定義了一行跳數索引能夠跳過多少個index_granularity區間的數據。

    作用規則如下:首先,按照index_granularity粒度間隔將數據劃分成n段,總共有[0 , n-1]個區間(n = total_rows /index_granularity,向上取整)。接著,根據索引定義時聲明的表達式,從0區間開始,依次按index_granularity粒度從數據中獲取聚合信息,每次向前移動1步(n+1),聚合信息逐步累加。最后,當移動granularity次區間時,則匯總并生成一行跳數索引數據。

    以minmax索引為例,假設index_granularity=8192且granularity=3,則數據會按照index_granularity劃分為n等份,MergeTree從第0段分區開始,依次獲取聚合信息。當獲取到第3個分區時(granularity=3),則匯總并會生成第一行minmax索引(前3段minmax極值匯總后取值為[1 , 9]),如下圖

    granularity作用規則

    數據標記

    如果把MergeTree比作一本書,primary.idx一級索引好比這本書的一級章節目錄,.bin文件中的數據好比這本書中的文字,那么數據標記(.mrk)就好比書簽一樣,會為一級章節目錄和具體的文字之間建立關聯。

    對于數據標記而言,它記錄了兩點重要信息:

    • 一級章節對應的頁碼信息。
    • 一段文字在某一頁中的起始位置信息。

    這樣一來,通過數據標記就能夠很快地從一本書中立即翻到關注內容所在的那一頁,并知道從第幾行開始閱讀。

    標記數據與一級索引數據不同,它并不能常駐內存,而是使用LRU(最近最少使用)緩存策略加快其取用速度。


    生成規則

    通過索引下標編號找到對應的數據標記

    從上圖可以看出,數據標記和索引區間是對齊的,均按照index_granularity的粒度間隔。如此一來,只需簡單通過索引區間的下標編號就可以直接找到對應的數據標記。

    為了能夠與數據銜接,數據標記文件也與.bin文件一一對應。即每一個列字段[Column].bin文件都有一個與之對應的[Column].mrk數據標記文件,用于記錄數據在.bin文件中的偏移量信息。同時,.mrk包含了.bin壓縮和解壓縮這兩種不同狀態的偏移量,如下圖

    標記數據示意圖

    工作方式

    MergeTree在讀取數據時,必須通過標記數據的位置信息才能夠找到所需要的數據。整個查找過程大致可以分為讀取壓縮數據塊讀取數據兩個步驟。

    對于下圖來說,表的index_granularity粒度為8192,所以一個索引片段的數據大小恰好是8192B。按照壓縮數據塊的生成規則,如果單個批次數據小于64KB,則繼續獲取下一批數據,直至累積到size>=64KB時,生成下一個壓縮數據塊。因此在JavaEnable的標記文件中,每8行標記數據對應1個壓縮數據塊(1B * 8192 = 8192B, 64KB = 65536B, 65536 / 8192 =8)。

    從圖能夠看到,其左側的標記數據中,8行數據的壓縮文件偏移量都是相同的,因為這8行標記都指向了同一個壓縮數據塊。而在這8行的標記數據中,它們的解壓縮數據塊中的偏移量,則依次按照8192B(每行數據1B,每一個批次8192行數據)累加,當累加達到65536(64KB)時則置0。因為根據規則,此時會生成下一個壓縮數據塊。

    JavaEnable字段的標記文件和壓縮數據文件的對應關系
  • 讀取壓縮數據塊:在查詢某一列數據時,MergeTree無須一次性加載整個.bin文件,而是可以根據需要,只加載特定的壓縮數據塊。而這項特性需要借助標記文件中所保存的壓縮文件中的偏移量。
  • 讀取數據:在讀取解壓后的數據時,MergeTree并不需要一次性掃描整段解壓數據,它可以根據需要,以index_granularity的粒度加載特定的一小段。為了實現這項特性,需要借助標記文件中保存的解壓數據塊中的偏移量。

  • 數據標記與壓縮數據塊的對應關系

    由于壓縮數據塊的劃分,與一個間隔index_granularity內的數據大小相關,每個壓縮數據塊的體積都被嚴格控制在64KB~1MB。而一個間隔index_granularity的數據,又只會產生一行數據標記。那么根據一個間隔內數據的實際字節大小,數據標記和壓縮數據塊之間會產生三種不同的對應關系。

    • 一對一
      • 一個數據標記對應一個壓縮數據塊,當一個間隔index_granularity內的數據未壓縮大小size大于等于64KB且小于等于1MB時,會出現這種對應關系。
    • 一對多
      • 一個數據標記對應多個壓縮數據塊,當一個間隔index_granularity內的數據未壓縮大小size直接大于1MB時,會出現這種對應關系。
    • 多對一
      • 多個數據標記對應一個壓縮數據塊,當一個間隔index_granularity內的數據未壓縮大小size小于64KB時,會出現這種對應關系。


    工作流程

    存儲流程

    數據的存儲流程主要有以下幾個步驟

    • 首先生成分區目錄,伴隨著每一批數據的寫入,都會生成一個新的分區目錄。
    • 在后續的某一時刻,屬于相同分區的目錄會依照規則合并到一起
    • 接著,按照index_granularity索引粒度,會分別生成primary.idx一級索引(如果聲明了二級索引,還會創建二級索引文件)、每一個列字段的.mrk數據標記和.bin壓縮數據文件。

    分區目錄、索引、標記和壓縮數據的生成過程示意

    查詢流程

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

    將掃描數據范圍最小化的過程

    如果一條查詢語句沒有指定任何WHERE條件,或是指定了WHERE條件,但條件沒有匹配到任何索引(分區索引、一級索引和二級索引),那么MergeTree就不能預先減小數據范圍。在后續進行數據查詢時,它會掃描所有分區目錄,以及目錄內索引段的最大區間。雖然不能減少數據范圍,但是MergeTree仍然能夠借助數據標記,以多線程的形式同時讀取多個壓縮數據塊,以提升性能。

    總結

    以上是生活随笔為你收集整理的ClickHouse 数据存储原理:MergeTree引擎的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 操操干| 男女无遮挡免费视频 | 中文字幕在线视频一区二区三区 | 99re这里有精品 | 极品超粉嫩尤物69xx | 一级黄色在线 | 香蕉久久久 | 四虎免费看黄 | 亚洲一区二区日韩 | 久久成年人视频 | 色多多视频在线 | 葵司av在线 | 蘑菇视频黄色 | 国产男男一区二区三区 | a在线看 | 户外少妇对白啪啪野战 | 体内射精一区二区 | 色xxxxxx| 国产成人综合av | 精品福利在线视频 | 亚洲一区二区三区蜜桃 | 毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 亚洲乱轮视频 | 亚洲第一综合网站 | 色综合天天色 | 欧美日韩免费观看一区=区三区 | 一区二区日韩国产 | 亚洲欧美自拍另类 | 日韩欧洲亚洲 | 国产精品久久久久久亚洲色 | 激情av网站 | 日本裸体网站 | 日本青草视频 | 免费黄色av网站 | 蜜桃视频导航 | 91成年影院 | 操出白浆视频 | 精品少妇一区二区三区 | av伦理在线 | 欧美色图一区二区三区 | 理论片第一页 | 日韩黄色免费视频 | 毛片毛片| 国产成人精品综合 | 日韩欧美高清片 | 欧美性视频网站 | 内射无码专区久久亚洲 | 国产最新视频在线 | 免费成人国产 | 在线天堂6 | 欧美综合国产 | 人人爱人人澡 | 成人精品视频在线播放 | 97在线视频人妻无码 | 国产深夜福利在线 | www.久久网 | 日本wwww色| 欧洲成人午夜精品无码区久久 | 五月婷婷啪啪 | 成人av网址大全 | 久综合| 国产精品zjzjzj在线观看 | 欧美一区免费观看 | 精品久久久久久久久久久aⅴ | 青青草在线免费观看 | 免费久久精品视频 | 亚洲欧美国产精品专区久久 | 天堂中文在线观看 | 一区二区高清视频 | 亚洲一区二区三区欧美 | 无码人妻丰满熟妇区五十路百度 | 青青久在线视频 | 两个女人互添下身爱爱 | 97福利在线| 潮喷失禁大喷水aⅴ无码 | 欧美大片黄| 伊人久久大香线蕉av一区 | 台湾男男gay做爽爽的视频 | 人人人妻人人澡人人爽欧美一区 | 久久久久亚洲精品 | www.色婷婷 | 美女视频一区二区三区 | 国产超碰人人 | 亚洲av永久无码精品一区二区国产 | 女人久久久久 | 国产精品免费一区二区三区都可以 | 欧洲久久久久 | 裸体女视频 | av福利院 | 亚洲综合不卡 | 国精品无码一区二区三区 | www.97视频| 爆操白虎逼 | 操网| 欧美在线视频精品 | 欧美另类在线播放 | 国产情侣一区二区三区 | 日韩人妻一区二区三区蜜桃 | 六月婷婷综合网 |