ClickHouse

ClickHouse シャーディングの方法とシャーディングされたテーブルへのSELECT方法

はじめに

ClickHouse引き続いてシャーディング周りの操作方法を確認したので書いておきます。が…正直書いている本人、これが正しいのかさらに懐疑的です。

設定(config.xml)

シャーディングの設定自体はReplicatedMergeTreeあたりと同じノリで行おうと思います。今回は試しに1号機と2号機のシャードを分けてみます。

1号機

/etc/clickhouse-server/config.xml
    <macros>
        <set>1</set>
        <shard>1</shard>
        <replica>clickhouse01</replica>
    </macros>

2号機

/etc/clickhouse-server/config.xml
    <macros>
        <set>1</set>
        <shard>2</shard>
        <replica>clickhouse01</replica>
    </macros>

分散した各サーバ全てにSELECTなどのクエリがいきわたるよう、今度はクラスターの設定を行います。zookeeperからクラスタ設定自動生成する手段、無いのかなー…。なお、クラスタ設定はオンラインで適用されるため、ClickHouseの再起動は不要です。不要なんですが、以前のクラスタ定義が、system.clustersテーブルに残り続けているので、不快な人は再起動したほうがいいかもしれません。

1号機2号機両方

/etc/clickhouse-server/config.xml
    <remote_servers>
        <cluster01>
            <shard>
                <replica>
                    <host>clickhouse01</host>
                    <port>9000</port>
                    <user>default</user>
                    <password></password>
                </replica>
            </shard>
            <shard>
                <replica>
                    <host>clickhouse02</host>
                    <port>9000</port>
                    <user>default</user>
                    <password></password>
                </replica>
            </shard>
        </cluster01>
    </remote_servers>

このように設定をいれておくと、クラスタ名「cluster01」で、2ノード構成で、互いの接続にはdefaultユーザを使う、という設定ができます。clickhouse01とclickhouse02はDNSやhostsで名前が引けるのが前提です。

データテーブル作成

とりあえずこんな風にして、再度ReplicatedMergeTreeテーブルを両方で作ります。

CREATE TABLE sharding_access_log_20171222 (
  log_date Date,
  url String,
  referrer String,
  ip String,
  ua String,
  created_at DateTime
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{set}-{shard}/sharding_access_log' , '{replica}', log_date, (log_date, url, referrer, ip, ua, created_at), 8192)

その後各々にデータを入れて、各々にSELECTを打ってみますが…各々のデータしか見えません。残念。

参照用のDistributedテーブルの作成

各サーバに散らばった各テーブルを参照するために、Distributedテーブルを作成します。内部的にはこれもViewに該当します。

CREATE TABLE d_sharding_access_log_20171222 (
  log_date Date,
  url String,
  referrer String,
  ip String,
  ua String,
  created_at DateTime
) ENGINE = Distributed(cluster01,default,sharding_access_log_20171222);

このd_sharding_access_log_20171222にSELECTを行うことで、2017/12/22分の全サーバのアクセスログを横断的に見ることができるようになりました。あと一歩ですね。

distributedテーブルをさらに横断的にみるMergeテーブルを作成

全日のデータを全シャード横断的にみるために、以下のようにまたまたViewとなるテーブルを作成します。

CREATE TABLE sharding_access_logs (
  log_date Date,
  url String,
  referrer String,
  ip String,
  ua String,
  created_at DateTime
) ENGINE = Merge(default,'^d_sharding_access_log_.*');

これで、このsharding_access_logsテーブルに対してSELECTを発行すれば全てのログが…見えます。

なお、Distributedテーブルを作る際にMergeテーブルを一度指定してみましたが、残念ながらエラーになりました。したがってこの順にマージしていく必要があるのかな、と思っています。