<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • clickhouse使用的一點總結

      clickhouse據說是用在大數據量的olap場景列式存儲數據庫,也有幸能夠用到它在實際場景中落地。本篇就來說說簡單的使用心得吧。

     

    1. 整體說明

      架構啥的,就不多說了,列式存儲、大數據量、高性能。參見官方文檔地址: https://clickhouse.com/docs/en/

      對于使用者而言,除了泛泛而談的架構之外,更多的是如何使用的問題。

      從整體而言,clickhouse的使用方法基本遵守普通的sql規范,所以基本上只要你會寫sql,對于普通的增刪改查就問題不大了。也就是說應對業務而言,問題并不大了。

      比如: create table...; select xx from t; insert into table xx... ; alter table xx update x=xx...;(當然了,這個用法差異有點大); alter table xx delete where x=xx...(同理);

     

    2. 存儲引擎簡說

      一個數據庫的最大特點,應該就是其存儲引擎或者說存儲方式。而這在clickhouse體現得更加明顯,其擁有超級多的存儲引擎,不管你用不用得上,反正可選范圍很大。

      其中,我們最常用或者最簡單可使用的是 MergeTree 系列,簡單來說是歸并樹的存儲結構,查詢肯定是很快的,另外,它也適用于大數據量的存儲。所以,一般就選擇這玩意就行了。當然,它下面有很多的子類,需要根據作出相應的改變。

      比如: ReplicatedMergeTree 代表有多節點存儲數據,這對于高可用查詢是必須的(針對任意節點的查詢也是必須的)。

      AggregatingMergeTree 代表當前節點是一種按主鍵聚合的數據分片方式。

      單就MergeTree引擎而言,如果想要有比較優化的應用或者比較特殊的需求,則必須要親自再去細細翻閱clickhouse的官方文檔了,太多選擇是真苦惱啊。

      其他存儲引擎,比如 Log系列,則更少場景會使用到,一般當作臨時表用時,可以考慮。其他的如 File, 則可以算是被當作解析器來使用。。。

      總之,要全面理解ck的存儲引擎,實非易事,除非深度使用它。

     

    3. clickhouse中的主鍵

      clickhouse中,其實并沒有明確說一定要有主鍵之類的話,只是在創建表時,會默認以排序字段作為主鍵。

      它的主鍵的作用,一定程度上相當于普通索引,這可能也是為什么它沒有明確叫主鍵的原因,因為不需要唯一但有利于查找。

      但它還是有  Primary Key 的定義。

     

    4. curd sql

      我們只說最簡單的方式,但其實clickhouse中,有一個非常大的特點就是,它的sql非常之多樣,靈活,不管你用不用得上,反正就是功能很多。而且文檔也是呵呵的。

    -- 創建表, 值得說明的是,它可以非常復雜的過期策略
    CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
    (
        name1 [type1] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|ALIAS expr1] [compression_codec] [TTL expr1],
        name2 [type2] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|ALIAS expr2] [compression_codec] [TTL expr2],
        PRIMARY KEY(expr1[, expr2,...])],
        ...
    ) ENGINE = MergeTree comment 'xxx'
    PARTITION BY toYYYYMM(d)
    TTL d + INTERVAL 1 MONTH [DELETE],
        d + INTERVAL 1 WEEK TO VOLUME 'aaa',
        d + INTERVAL 2 WEEK TO DISK 'bbb';
    -- 更新和刪除,這語法夠獨特的,據說是為了讓大家少用這種功能而設計的,厲害了
    ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] WHERE filter_expr
    ALTER TABLE [db.]table [ON CLUSTER cluster] DELETE WHERE filter_expr
    -- 查詢,有很多獨特的用法,如WITH
    [WITH expr_list|(subquery)]
    SELECT [DISTINCT [ON (column1, column2, ...)]] expr_list
    [FROM [db.]table | (subquery) | table_function] [FINAL]
    [SAMPLE sample_coeff]
    [ARRAY JOIN ...]
    [GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN (subquery)|table (ON <expr_list>)|(USING <column_list>)
    [PREWHERE expr]
    [WHERE expr]
    [GROUP BY expr_list] [WITH ROLLUP|WITH CUBE] [WITH TOTALS]
    [HAVING expr]
    [ORDER BY expr_list] [WITH FILL] [FROM expr] [TO expr] [STEP expr]
    [LIMIT [offset_value, ]n BY columns]
    [LIMIT [n, ]m] [WITH TIES]
    [SETTINGS ...]
    [UNION  ...]
    [INTO OUTFILE filename [COMPRESSION type] ]
    [FORMAT format]
    -- 數據插入,可以作排除性插入語法
    INSERT INTO [db.]table [(c1, c2, c3)] VALUES (v11, v12, v13), (v21, v22, v23), ...
    INSERT INTO [db.]table [(c1, c2, c3)] SELECT ...
    INSERT INTO insert_select_testtable (* EXCEPT(b)) Values (2, 2);
    -- 執行計劃查詢,這對于了解其內部機制很有幫助,它的執行計劃非常詳細,不過看起來也有點嚇人
    EXPLAIN [AST | SYNTAX | PLAN | PIPELINE] [setting = value, ...] SELECT ... [FORMAT ...]


    5. 本地與集群

      雖然clickhouse號稱是大數據量實時分析數據庫,但它不絕對的使用分布式存儲。而是構造了兩個名詞供選擇,即本地表與分布式表。

      本地表顧名思義就是,只是存儲在本地機器上的表。這種本地表,只應對某些場景,比如你連接的節點永遠是同一個機器時,可以使用,此時它和mysql之類的數據庫是一樣的,存儲容量和性能都是單機的,但有點值得注意的是當它與分布表進行關聯查詢時,可能會有你意想不到的結果:報錯。

      分布式表,就是說它可以每個節點上都能查詢到。這是我們理解的真正的大數據量的分布式存儲,我也不關心數據存儲在哪里。只要能給到正確的結果就行。實際上,分布表的背后,是一個個的本地表。不過,它一般會要求有副本存儲機制。

      但是很無賴的是,我們無法直接創建分布式表,而是要先創建本地表,然后再以此為基礎創建對應的分布式表。即一個建表工作,我們需要做兩遍才能完成。

      而且,對于數據的寫入,你可以往本地表寫,也可以往分布式表寫。雖然入口的確變多了,但也給了大家很迷惑的感覺。

    -- 創建人群原始表
    create table loc_tab1 ON CLUSTER ck_cluster (
        xx String comment 'xx',
        version_no String comment 'version, for update'
    ) ENGINE = ReplicatedMergeTree
    partition by xx
    order by xx
    ;
    -- 創建分布式表
    CREATE TABLE distributed_tab2 AS loc_tab1 ENGINE = Distributed(ck_cluster, currentDatabase(), loc_tab1, rand());

      

    6. bitmap數據操作參考

      bitmap數據由于其有著超高性能的交差運算能力,以及節省存儲空間的能力,被我們某些場景應用,如碼值數據表。但是為構建bitmap數據,則往往要做比較多的前置工作,而且由于bitmap的數據壓縮,可能會無法應對復雜場景,這些都需要提前評估。

    -- 創建原始bitmap表
    create table loc_tab1_bitmap ON CLUSTER ck_cluster (
        xx String comment 'xx',
        uv AggregateFunction(groupBitmap, UInt64),
        version_no String comment 'version, for update'
    ) ENGINE = ReplicatedMergeTree
    partition by xx
    order by xx
    ;
    -- 創建分布式表
    CREATE TABLE distributed_tab2_bitmap AS loc_tab1_bitmap ENGINE = Distributed(ck_cluster, currentDatabase(), loc_tab1_bitmap, rand());
    -- 插入人群bitmap表數據, 往本地表插數據,往分布式表讀數據
    -- 讀取的數據來源表,一般也會要求是一個分布寬表,而且其作用如果只是為了構建bitmap數據,則會有一個用后即刪的動作
    insert into loc_tab1_bitmap
        select xx, groupBitmapState(toUInt64OrZero(uid)) as uv,version_no
        from dist_data_raw
        group by xx,version_no;
    -- 讀取參考,求兩個bitmap數據的交集,并到另一個表中做group by 
    with intersect_tab as ( select arrayJoin(bitmapToArray(bitmapAnd(user1, user2))) as uid  from (select uv as user1, 1 as join_id from distributed_tab2_bitmap   where xx = '1') t1  inner join (select uv as user2, 1 as join_id from distributed_tab2_bitmap   where  xx = '2') t2  on t1.join_id = t2.join_id ),a1 as (select x2, toUInt64(xx) as uid from distributed_tb3)  select x2,count(1) as cnt from a1 right join intersect_tab a2 on a1.uid = a2.uid group by x2 order by cnt desc

     

    posted @ 2021-12-03 09:31  等你歸去來  閱讀(620)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看