ClickHouse/docs/ja/sql-reference/statements/alter/projection.md
2024-11-18 11:58:58 +09:00

6.5 KiB

slug sidebar_position sidebar_label title
/ja/sql-reference/statements/alter/projection 49 PROJECTION プロジェクション

プロジェクションはクエリ実行を最適化する形式でデータを保存します。この機能は次の用途に便利です:

  • 主キーの一部でないカラムに対するクエリの実行
  • カラムの事前集計により、計算とIOの両方を削減

テーブルに対して1つ以上のプロジェクションを定義することができ、クエリ解析時にユーザーの指定したクエリを変更せずに、スキャンすべきデータが最小のプロジェクションをClickHouseが選択します。

:::note ディスク使用量

プロジェクションは内部で新しい隠しテーブルを作成するため、より多くのIOとディスクスペースが必要になります。 例として、異なる主キーを定義したプロジェクションがある場合、元のテーブルからのすべてのデータが複製されます。 :::

プロジェクションの内部動作に関する技術的な詳細はこのページをご覧ください。

主キーを使用せずにフィルタリングする例

テーブルの作成:

CREATE TABLE visits_order
(
   `user_id` UInt64,
   `user_name` String,
   `pages_visited` Nullable(Float64),
   `user_agent` String
)
ENGINE = MergeTree()
PRIMARY KEY user_agent

ALTER TABLEを使って既存のテーブルにプロジェクションを追加することができます:

ALTER TABLE visits_order ADD PROJECTION user_name_projection (
SELECT
*
ORDER BY user_name
)

ALTER TABLE visits_order MATERIALIZE PROJECTION user_name_projection

データの挿入:

INSERT INTO visits_order SELECT
    number,
    'test',
    1.5 * (number / 2),
    'Android'
FROM numbers(1, 100);

プロジェクションを使用することで、元のテーブルでuser_namePRIMARY_KEYとして定義されていなくても、user_nameでのフィルタリングを素早く行えます。クエリ時にClickHouseは、プロジェクションを使用することでデータの処理量が少なくなると判断します。なぜなら、データがuser_nameでソートされているからです。

SELECT
    *
FROM visits_order
WHERE user_name='test'
LIMIT 2

クエリがプロジェクションを使用しているか確認するには、system.query_logテーブルを確認します。projectionsフィールドには使用されたプロジェクションの名前が入り、未使用の場合は空になります:

SELECT query, projections FROM system.query_log WHERE query_id='<query_id>'

集計前のクエリの例

プロジェクションを使用してテーブルを作成:

CREATE TABLE visits
(
   `user_id` UInt64,
   `user_name` String,
   `pages_visited` Nullable(Float64),
   `user_agent` String,
   PROJECTION projection_visits_by_user
   (
       SELECT
           user_agent,
           sum(pages_visited)
       GROUP BY user_id, user_agent
   )
)
ENGINE = MergeTree()
ORDER BY user_agent

データの挿入:

INSERT INTO visits SELECT
    number,
    'test',
    1.5 * (number / 2),
    'Android'
FROM numbers(1, 100);
INSERT INTO visits SELECT
    number,
    'test',
    1. * (number / 2),
   'IOS'
FROM numbers(100, 500);

user_agentフィールドを使ったGROUP BYクエリを最初に実行します。このクエリは事前集計が一致しないため、定義されたプロジェクションを使用しません。

SELECT
    user_agent,
    count(DISTINCT user_id)
FROM visits
GROUP BY user_agent

プロジェクションを使用するためには、事前集計またはGROUP BYフィールドの一部またはすべてを選択するクエリを実行します。

SELECT
    user_agent
FROM visits
WHERE user_id > 50 AND user_id < 150
GROUP BY user_agent
SELECT
    user_agent,
    sum(pages_visited)
FROM visits
GROUP BY user_agent

前述のように、system.query_logテーブルを確認できます。projectionsフィールドには使用されたプロジェクションの名前が入り、未使用の場合は空になります:

SELECT query, projections FROM system.query_log WHERE query_id='<query_id>'

プロジェクションの操作

次の操作がプロジェクションで利用可能です:

ADD PROJECTION

ALTER TABLE [db.]name [ON CLUSTER cluster] ADD PROJECTION [IF NOT EXISTS] name ( SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY] ) - テーブルのメタデータにプロジェクションの説明を追加します。

DROP PROJECTION

ALTER TABLE [db.]name [ON CLUSTER cluster] DROP PROJECTION [IF EXISTS] name - テーブルのメタデータからプロジェクションの説明を削除し、プロジェクションのファイルをディスクから削除します。ミューテーションとして実装されています。

MATERIALIZE PROJECTION

ALTER TABLE [db.]table [ON CLUSTER cluster] MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name] - 指定されたパーティションpartition_name内のプロジェクションnameを再構築します。ミューテーションとして実装されています。

CLEAR PROJECTION

ALTER TABLE [db.]table [ON CLUSTER cluster] CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name] - 説明を削除せずにプロジェクションのファイルをディスクから削除します。ミューテーションとして実装されています。

ADDDROPCLEARコマンドはメタデータの変更やファイルの削除のみを行う軽量な操作です。

また、これらはClickHouse KeeperまたはZooKeeperを介してプロジェクションのメタデータを同期することによりレプリケーションされます。

:::note プロジェクションの操作は*MergeTreeエンジン(レプリケートされたバリアントを含む)のテーブルでのみサポートされています。 :::