辞書
ClickHouse のディクショナリーは、さまざまな 内部および外部ソース からのデータのインメモリ キーと値 表現を提供し、超低遅延のルックアップクエリを最適化します。
ディクショナリーは以下の用途に役立ちます:
- 特に
JOIN
と併用したときのクエリパフォーマンスを向上させる - データの取り込みプロセスを遅延させずに、取り込まれたデータをその場でリッチ化する

Speeding up joins using a Dictionary
ディクショナリーは、特定のタイプの JOIN
を高速化するために使用できます: LEFT ANY
タイプ で、結合キーは基となるキーと値のストレージのキー属性と一致する必要があります。

この場合、ClickHouse はディクショナリーを活用して Direct Join を実行できます。これはClickHouseの最速の結合アルゴリズムであり、右側のテーブルが低遅延のキーと値のリクエストをサポートするテーブルエンジンを使用している場合に適用されます。ClickHouse には、この機能を提供する3つのテーブルエンジンがあります:Join(基本的に事前計算されたハッシュテーブル)、EmbeddedRocksDB、および Dictionary です。ここではディクショナリーに基づくアプローチを説明しますが、メカニズムはすべての3つのエンジンで同じです。
直接結合アルゴリズムでは、右側のテーブルがディクショナリーにバックアップされている必要があり、そのテーブルから結合するデータがすでにメモリ内に低遅延のキーと値のデータ構造の形で存在している必要があります。
Example
Stack Overflow データセットを使用して、次の質問に答えます: Hacker News の SQL に関する最も物議を醸す投稿は何ですか?
物議を醸すとは、投稿のアップおよびダウン投票の数が類似している場合と定義します。私たちはこの絶対的な差を計算し、0 に近い値がより物議を醸すことを意味します。投稿は少なくとも10のアップとダウンの投票が必要だと仮定します - 投票されない投稿はあまり物議を醸しません。
データが正規化されている場合、このクエリは現在 posts
テーブルと votes
テーブルを使用して JOIN
を必要とします:
右側の
JOIN
で小さなデータセットを使用する:このクエリは、必要以上に冗長に見えるかもしれません。PostId
でのフィルタリングが外側のクエリとサブクエリの両方で発生します。これは、クエリの応答時間を迅速にするためのパフォーマンス最適化です。最適なパフォーマンスを得るためには、常にJOIN
の右側が小さいセットで、可能な限り小さいことを確認してください。JOIN
のパフォーマンスを最適化し、利用可能なアルゴリズムを理解するためのヒントについては、この一連のブログ記事をお勧めします。
このクエリは迅速ですが、良好なパフォーマンスを達成するためには、JOIN
を慎重に記述する必要があります。理想的には、UpVote
と DownVote
のカウントを計算するために、SQL
を含む投稿をフィルタリングするだけで済むはずです。
Applying a dictionary
これらの概念を示すために、私たちは投票データにディクショナリーを使用します。ディクショナリーは通常メモリ内に保持されますが、ssd_cache が例外ですので、ユーザーはデータのサイズに注意する必要があります。votes
テーブルのサイズを確認します:
データはディクショナリー内で非圧縮で保存されるため、すべてのカラム(私たちはそうしませんが)をディクショナリーに保存する場合、少なくとも4GBのメモリが必要です。ディクショナリーはクラスタ全体にレプリケートされるため、このメモリ量は 各ノードごと に確保する必要があります。
以下の例では、ディクショナリーのデータは ClickHouse テーブルから派生しています。これはディクショナリーの最も一般的なソースですが、ファイル、http、Postgres などのデータベースを含む 多くのソース がサポートされています。例示するように、ディクショナリーは自動的に更新され、小さいデータセットが頻繁に変更される場合に直接結合に利用できる理想的な方法を提供します。
私たちのディクショナリーは、ルックアップを実行するための主キーが必要です。これは、トランザクショナルデータベースの主キーと概念的に同じで、ユニークである必要があります。上記のクエリは、結合キー - PostId
のルックアップを必要とします。ディクショナリーは、votes
テーブルからの各 PostId
に対するアップ票とダウン票の合計で構成される必要があります。このディクショナリーのデータを取得するためのクエリは次の通りです:
ディクショナリーを作成するには、次の DDL が必要です - 上記のクエリを使用しています:
セルフマネージド OSS では、上記のコマンドはすべてのノードで実行する必要があります。ClickHouse Cloud では、ディクショナリーがすべてのノードに自動的にレプリケートされます。上記は、64GBのRAMを搭載したClickHouse Cloudノードで実行され、36秒でロードされました。
ディクショナリーによって消費されるメモリを確認します:
特定の PostId
のアップ票とダウン票を取得するためには、シンプルな dictGet
関数を使用できます。以下に、投稿 11227902
の値を取得します:
このクエリは非常にシンプルであるだけでなく、実行速度も2倍以上向上しています!さらに最適化するためには、10票以上のアップ票とダウン票を持つ投稿のみをディクショナリーにロードし、予め計算された物議の値を保存することが可能です。
Query time enrichment
ディクショナリーは、クエリ時に値をルックアップするために使用できます。これらの値は結果に返されるか、集計に使用されます。たとえば、ユーザーIDをその場所にマッピングするディクショナリーを作成しましょう:
このディクショナリーを使用して、投稿結果をリッチ化できます:
上記の結合の例と同様に、同じディクショナリーを使用して、投稿の多くがどこから来ているのかを効率的に特定できます:
Index time enrichment
上の例では、クエリ時にディクショナリーを使用して結合を削除しました。ディクショナリーは、挿入時に行をリッチ化するためにも使用できます。これは通常、強化値が変更せず、外部ソースに存在していてディクショナリーをポピュレートするために使用できる場合に適しています。この場合、挿入時に行をリッチ化することで、ディクショナリーへのクエリ時のルックアップを回避します。
Stack Overflow のユーザーの Location
が変更されないと仮定します(実際には変更されます) - 特に users
テーブルの Location
カラムです。投稿テーブルを場所別に分析したいとしましょう。このテーブルには UserId
が含まれています。
ディクショナリーは、ユーザーIDを場所にマッピングするもので、users
テーブルによってバックアップされています:
Id < 0
のユーザーは除外します。これにより、Hashed
ディクショナリータイプを使用できます。Id < 0
のユーザーはシステムユーザーです。
このディクショナリーを利用して挿入時に投稿テーブルを強化するには、スキーマを変更する必要があります:
上記の例では、Location
が MATERIALIZED
カラムとして宣言されています。これは、値が INSERT
クエリの一部として提供され、常に計算されることを意味します。
ClickHouse は、提供されない場合に値を挿入または計算できる
DEFAULT
カラム もサポートしています。
テーブルをポピュレートするには、S3 から通常の INSERT INTO SELECT
を使用できます:
これで、ほとんどの投稿がどこから来ているのかを示す場所の名前を取得できます:
Advanced Dictionary Topics
Choosing the Dictionary LAYOUT
LAYOUT
句は、ディクショナリーの内部データ構造を制御します。いくつかのオプションが存在し、ここ に文書化されています。正しいレイアウトを選択するためのいくつかのヒントは ここ にあります。
Refreshing dictionaries
ディクショナリーに LIFETIME
を MIN 600 MAX 900
と指定しています。LIFETIME はディクショナリーの更新間隔であり、ここでの値は600秒から900秒の間のランダムな間隔での定期的なリロードを引き起こします。このランダムな間隔は、大量のサーバーで更新する際にディクショナリーソースへの負荷を分散させるために必要です。更新中、ディクショナリーの古いバージョンはまだクエリでき、初回のロードのみがクエリをブロックします。(LIFETIME(0))
を設定すると、ディクショナリーが更新されないことに注意してください。
ディクショナリーは SYSTEM RELOAD DICTIONARY
コマンドを使用して強制的にリロードできます。
ClickHouse や Postgres などのデータベースソースでは、ディクショナリーを更新するためのクエリを設定して、定期的な間隔で更新されるのではなく、実際に変更があった場合のみ更新することができます。これについての詳細は ここ にあります。
Other dictionary types
ClickHouse は、階層型、ポリゴン、および 正規表現 ディクショナリーもサポートしています。