アナライザー
既知の非互換性
ClickHouseバージョン24.3では、新しいクエリアナライザーがデフォルトで有効になりました。多くのバグを修正し新たな最適化を導入した一方で、ClickHouseの動作にいくつかの破壊的変更が加わっています。新しいアナライザーに合わせてクエリを書き直す方法を理解するために、以下の変更をお読みください。
無効なクエリは最適化されなくなりました
以前のクエリプランニングインフラストラクチャでは、クエリの検証ステップよりも前にASTレベルの最適化が適用されていました。この最適化により、初期のクエリが書き換えられ、実行可能になっていました。
新しいアナライザーでは、最適化ステップの前にクエリの検証が行われます。これにより、以前は実行可能だった無効なクエリはサポートされなくなりました。このような場合、クエリを手動で修正する必要があります。
例1:
SELECT number
FROM numbers(1)
GROUP BY toString(number)
このクエリでは、numberカラムが集計後に利用可能なtoString(number)だけでプロジェクションリストに使用されています。古いアナライザーでは、GROUP BY toString(number)がGROUP BY numberに最適化され、クエリが有効になっていました。
例2:
SELECT
number % 2 AS n,
sum(number)
FROM numbers(10)
GROUP BY n
HAVING number > 5
このクエリでも同じ問題が発生します。カラムnumberが異なるキーで集計後に使用されています。以前のクエリアナライザーはこのクエリを修正し、HAVING句からWHERE句にnumber > 5フィルタを移動しました。
クエリを修正するには、非集計カラムに適用されるすべての条件を標準SQL構文に従ってWHEREセクションに移動する必要があります。
SELECT
number % 2 AS n,
sum(number)
FROM numbers(10)
WHERE number > 5
GROUP BY n
無効なクエリでのCREATE VIEW
新しいアナライザーでは常に型チェックが行われます。以前は、無効なSELECTクエリでVIEWを作成することが可能でした。最初のSELECTまたはINSERT(MATERIALIZED VIEWの場合)で失敗していました。
今では、そのようなVIEWを作成することはできません。
例:
CREATE TABLE source (data String) ENGINE=MergeTree ORDER BY tuple();
CREATE VIEW some_view
AS SELECT JSONExtract(data, 'test', 'DateTime64(3)')
FROM source;
JOIN句の既知の非互換性
プロジェクションからカラムを使用するジョイン
デフォルトでは、エイリアスはSELECTリストからJOIN USINGキーとして使用できません。
新しい設定analyzer_compatibility_join_using_top_level_identifierを有効にすると、JOIN USINGの動作が変わり、SELECTクエリのプロジェクションリストからの式に基づいて識別子を解決するのが優先され、左テーブルから直接カラムを使用しません。
例:
SELECT a + 1 AS b, t2.s
FROM Values('a UInt64, b UInt64', (1, 1)) AS t1
JOIN Values('b UInt64, s String', (1, 'one'), (2, 'two')) t2
USING (b);
analyzer_compatibility_join_using_top_level_identifierをtrueに設定すると、ジョイン条件はt1.a + 1 = t2.bと解釈され、従来のバージョンの動作と一致します。結果は2, 'two'となります。
設定がfalseの場合、ジョイン条件はt1.b = t2.bにデフォルト設定され、クエリは2, 'one'を返します。
t1にbが存在しない場合、クエリはエラーで失敗します。
JOIN USINGとALIAS/MATERIALIZEDカラムの動作変更
新しいアナライザーでは、ALIASやMATERIALIZEDカラムを含むJOIN USINGクエリで*を使用すると、デフォルトでこれらのカラムが結果セットに含まれます。
例:
CREATE TABLE t1 (id UInt64, payload ALIAS sipHash64(id)) ENGINE = MergeTree ORDER BY id;
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (id UInt64, payload ALIAS sipHash64(id)) ENGINE = MergeTree ORDER BY id;
INSERT INTO t2 VALUES (2), (3);
SELECT * FROM t1
FULL JOIN t2 USING (payload);
新しいアナライザーでは、このクエリの結果には両方のテーブルからidとともにpayloadカラムが含まれます。これに対し、以前のアナライザーはこれらのALIASカラムを含めるために特定の設定(asterisk_include_alias_columnsまたはasterisk_include_materialized_columns)を有効にする必要があり、カラムの順序が異なる場合がありました。
特に古いクエリを新しいアナライザーに移行する際には、*の代わりにSELECT句で明示的にカラムを指定することを推奨します。
USING句におけるタイプ修飾子の処理
新しいアナライザーでは、USING句で指定されたカラムの共通スーパータイプを求めるルールが標準化され、特にLowCardinalityやNullableのようなタイプ修飾子を扱う際に、より予測可能な結果を生み出します。
LowCardinality(T)とT:LowCardinality(T)型のカラムがT型のカラムと結合される場合、共通のスーパータイプはTとなり、LowCardinality修飾子は破棄されます。Nullable(T)とT:Nullable(T)型のカラムがT型のカラムと結合される場合、共通のスーパータイプはNullable(T)となり、nullableの特性は保持されます。
例:
SELECT id, toTypeName(id) FROM Values('id LowCardinality(String)', ('a')) AS t1
FULL OUTER JOIN Values('id String', ('b')) AS t2
USING (id);
このクエリでは、idの共通スーパータイプはStringと判断され、t1のLowCardinality修飾子は破棄されます。
プロジェクションカラム名の変更
プロジェクション名の計算中、エイリアスは置き換えられません。
SELECT
1 + 1 AS x,
x + 1
SETTINGS enable_analyzer = 0
FORMAT PrettyCompact
┌─x─┬─plus(plus(1, 1), 1)─┐
1. │ 2 │ 3 │
└───┴─────────────────────┘
SELECT
1 + 1 AS x,
x + 1
SETTINGS enable_analyzer = 1
FORMAT PrettyCompact
┌─x─┬─plus(x, 1)─┐
1. │ 2 │ 3 │
└───┴────────────┘
非互換の関数引数タイプ
新しいアナライザーでは、初期クエリアナリシス中に型推論が行われます。この変更により、型チェックはショートサーキット評価の前に行われ、if関数の引数は常に共通のスーパータイプを持たなければなりません。
例:
次のクエリはThere is no supertype for types Array(UInt8), String because some of them are Array and some of them are notというエラーで失敗します:
SELECT toTypeName(if(0, [2, 3, 4], 'String'))
異種クラスター
新しいアナライザーはクラスタ内のサーバー間の通信プロトコルを大幅に変更しました。そのため、異なるenable_analyzer設定値を持つサーバーで分散クエリを実行することは不可能です。
ミューテーションは以前のアナライザーによって解釈されます
ミューテーションはまだ古いアナライザーを使用しており、このため、新しいClickHouse SQL機能はミューテーションで使用できません。例えば、QUALIFY句です。ステータスはこちらで確認できます。
サポートされていない機能
新しいアナライザーが現時点でサポートしていない機能の一覧:
- Annoyインデックス。
- Hypothesisインデックス。進行中の作業はこちら。
- ウィンドウビューはサポートされていません。将来的にサポートされる予定はありません。