Wikipedia の統計データセットに対するクエリ方法を見てきたので、次は ClickHouse でのストレージ効率の最適化に焦点を当てます。 このセクションでは、クエリパフォーマンスを維持しながらストレージ要件を削減するための実践的な手法を紹介します。
型の最適化
ストレージ効率を最適化する一般的な方法は、適切なデータ型を使用することです。
project と subproject のカラムを見てみましょう。これらのカラムは String 型ですが、一意の値の数は比較的少数です。
SELECT
uniq(project),
uniq(subproject)
FROM wikistat;┌─uniq(project)─┬─uniq(subproject)─┐
│ 1332 │ 130 │
└───────────────┴──────────────────┘つまり、辞書ベースのエンコーディングを使用する LowCardinality() データ型を使えるということです。これにより、ClickHouse は元の文字列値ではなく内部の値 ID を保存するため、容量を大幅に節約できます。
ALTER TABLE wikistat
MODIFY COLUMN `project` LowCardinality(String),
MODIFY COLUMN `subproject` LowCardinality(String)hits カラムには UInt64 型も使用しています。これは 8 バイトを使用しますが、最大値は比較的小さめです。
SELECT max(hits)
FROM wikistat;┌─max(hits)─┐
│ 449017 │
└───────────┘この値であれば、代わりに UInt32 を使用できます。必要な容量は 4 バイトだけで、最大で約40億まで格納できます。
ALTER TABLE wikistat
MODIFY COLUMN `hits` UInt32;これにより、メモリ内のこのカラムのサイズを少なくとも半分にできます。なお、圧縮されるため、ディスク上のサイズは変わりません。ただし、データ型は小さすぎるものを選ばないよう注意してください。
特殊なコーデック
時系列データのような連続したデータを扱う場合は、特殊なコーデックを使うことでストレージ効率をさらに高められます。 基本的な考え方は、値そのものではなく値の変化分を保存するというもので、変化が緩やかなデータでは必要な容量を大幅に削減できます。
ALTER TABLE wikistat
MODIFY COLUMN `time` CODEC(Delta, ZSTD);time カラムには Delta コーデック を使用しています。これは時系列データに適しています。
適切な ordering key を選ぶことでも、ディスク容量を節約できます。
通常は path で絞り込みを行いたいため、sorting key に path を追加します。
そのため、テーブル を再作成する必要があります。
以下に、初期の テーブル と最適化後の テーブル の CREATE コマンドを示します。
CREATE TABLE wikistat
(
`time` DateTime,
`project` String,
`subproject` String,
`path` String,
`hits` UInt64
)
ENGINE = MergeTree
ORDER BY (time);CREATE TABLE optimized_wikistat
(
`time` DateTime CODEC(Delta(4), ZSTD(1)),
`project` LowCardinality(String),
`subproject` LowCardinality(String),
`path` String,
`hits` UInt32
)
ENGINE = MergeTree
ORDER BY (path, time);それでは、各テーブルのデータが占める容量を見てみましょう:
SELECT
table,
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
formatReadableSize(sum(data_compressed_bytes)) AS compressed,
count() AS parts
FROM system.parts
WHERE table LIKE '%wikistat%'
GROUP BY ALL;┌─table──────────────┬─uncompressed─┬─compressed─┬─parts─┐
│ wikistat │ 35.28 GiB │ 12.03 GiB │ 1 │
│ optimized_wikistat │ 30.31 GiB │ 2.84 GiB │ 1 │
└────────────────────┴──────────────┴────────────┴───────┘最適化されたテーブルは、圧縮形式では占有容量が4分の1弱になります。