ストレージ層: 同時実行される挿入は互いに分離されている
ストレージ層: 同時実行される INSERT と SELECT は分離される
ストレージ層: マージ時の計算
- Replacing merges は、入力パーツ内の行について最新バージョンだけを残し、それ以外のバージョンはすべて破棄します。Replacing merges は、マージ時に行うクリーンアップ処理と考えることができます。
- Aggregating merges は、入力パート内の中間集計状態を新しい集計状態へと結合します。少しわかりにくく感じるかもしれませんが、実際に行っているのは増分集計の実装にすぎません。
- TTL (time-to-live) merges は、時間ベースのルールに基づいて行を圧縮、移動、または削除します。
ストレージ層: データプルーニング
- テーブルデータのソート順を定義する 主キー索引。適切に選ばれた主キーを使うことで、 (上記のクエリの WHERE 句のような) フィルタを、カラム全体の走査ではなく高速な二分探索で評価できます。より技術的に言えば、走査の実行時間はデータサイズに対して線形ではなく対数的になります。
- 同じデータを保持しつつ、別の主キーでソートして格納する、テーブルの代替となる内部バージョンである テーブルプロジェクション。プロジェクションは、頻出するフィルタ条件が複数ある場合に役立ちます。
- カラムに追加の統計情報を埋め込む スキッピング索引。たとえば、カラムの最小値と最大値、一意な値の集合などです。スキッピング索引は主キーやテーブルプロジェクションとは独立しており、カラム内のデータ分布によっては、フィルタの評価を大幅に高速化できます。
ストレージ層: データ圧縮
最先端のクエリ処理層
細部への徹底したこだわり
「ClickHouse は異様なシステムです。20 種類ものハッシュテーブルがある。ほとんどのシステムはハッシュテーブルを 1 つしか持っていないのに、こんなにもすばらしい仕組みがそろっている … ClickHouse が驚異的な性能を発揮するのは、こうした特化したコンポーネントを数多く備えているからです」 Andy Pavlo, CMU のデータベース教授ClickHouse を際立たせているのは、低レベル最適化に対する徹底したこだわりです。単に動作するデータベースを作るのと、多様なクエリタイプ、データ構造、データ分布、索引構成にわたって高速性を発揮できるように設計するのとはまったく別物であり、そこにこそ「異様なシステム」たる真価が光ります。 Hash Tables. 例として、ハッシュテーブルを取り上げましょう。ハッシュテーブルは、JOIN や集計で使われる中核的なデータ構造です。プログラマは、次のような設計上の判断を考える必要があります。
- どのハッシュ関数を選ぶか
- 衝突解決方式は open addressing か chaining か
- メモリレイアウトはどうするか: キーと値を 1 つの配列に入れるのか、別々の配列にするのか
- 充填率はどうするか: いつ、どのようにリサイズするか。リサイズ時に値をどう移動するか
- 削除: ハッシュテーブルでエントリの追い出しを許可すべきか
- 何をソートするのか: 数値、タプル、文字列、それとも構造体か
- データは RAM 上にあるか
- 安定ソートが必要か
- すべてのデータをソートすべきか、それとも部分ソートで十分か