24.3 では、アナライザがデフォルトで有効化されました。
その動作の詳細については、こちらをご覧ください。
バージョン 26.9 以降、アナライザは必須となりました。enable_analyzer 設定は廃止され、0 に設定しようとしても拒否されます。また、24.3 より前の ClickHouse で使用されていたクエリ解析はサポートされません。以下に挙げる非互換性は、その古い解析との違いを示すものであり、古い解析向けに書かれたクエリを更新する際の参考となります。古い解析の動作を確認したい場合は、26.9 より古いバージョンの ClickHouse でクエリを実行してください。
既知の非互換性
多数のバグ修正と新たな最適化の導入に伴い、ClickHouse の動作には互換性に影響する変更もいくつか含まれています。アナライザに対応するようクエリをどのように書き換える必要があるかを判断するために、以下の変更点を確認してください。無効なクエリは最適化されなくなりました
従来のクエリプランニング基盤では、クエリの検証ステップの前に AST レベルの最適化が適用されていました。 その結果、元のクエリが有効で実行可能な形に書き換えられることがありました。 アナライザでは、クエリの検証は最適化ステップより前に行われます。 つまり、以前は実行できていた無効なクエリは、現在ではサポートされません。 そのような場合は、クエリを手動で修正する必要があります。例 1
次のクエリでは、集約後に利用できるのはtoString(number) のみであるにもかかわらず、PROJECTIONリストでカラム number を使用しています。
古いアナライザでは、GROUP BY toString(number) は GROUP BY number, に最適化されることで、このクエリは有効とみなされていました。
例 2
同じ問題はこのクエリでも発生します。カラムnumber は、別のキーで集約した後に使用されています。
以前のクエリアナライザは、number > 5 のフィルタを HAVING 句から WHERE 句へ移動することで、このクエリを修正していました。
WHERE 句に移動する必要があります。
HAVING 句から WHERE 句への 書き換え を再現できます。この動作を有効にするには、analyzer_compatibility_allow_non_aggregate_in_having = 1 を設定してください。この設定は ClickHouse 26.7 以降で利用できます。この設定は、WITH CUBE、WITH ROLLUP、WITH TOTALS、および GROUPING SETS では無視されます。集約、grouping、または非決定論的関数を含む条件は HAVING に残ります。いずれかの条件にウィンドウ関数または状態を持つ関数 (たとえば rowNumberInBlock) が含まれている場合は、従来の legacy の動作に合わせて、HAVING 全体に対する 書き換え が無効になります。
無効なクエリを含む CREATE VIEW
アナライザは常に型チェックを行います。
以前は、無効な SELECT クエリを含む VIEW を作成できました。
その場合、最初の SELECT または INSERT の実行時に失敗していました (MATERIALIZED VIEW の場合) 。
このような方法で VIEW を作成することは、現在ではできません。
例
JOIN句の既知の非互換性
PROJECTIONのカラムを使った JOIN
SELECT リストのエイリアスは、デフォルトでは JOIN USING のキーとして使用できません。
新しい設定 analyzer_compatibility_join_using_top_level_identifier を有効にすると、JOIN USING の動作が変わり、左側のテーブルのカラムを直接使う代わりに、SELECT クエリのPROJECTIONリスト内の式に基づいて識別子を優先的に解決するようになります。
例えば:
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 クエリで * を使用すると、デフォルトでそれらのカラムも結果セットに含まれます。
たとえば:
id とともに payload カラムが含まれます。
一方、以前のアナライザでは、特定の設定 (asterisk_include_alias_columns または asterisk_include_materialized_columns) が有効になっている場合にのみ、これらの ALIAS カラムが含まれ、
カラムの順序も異なる場合がありました。
一貫性があり期待どおりの結果を得るため、特に古いクエリをアナライザに移行する際は、* を使うのではなく、SELECT 句でカラムを明示的に指定することを推奨します。
USING 句におけるカラムの型修飾子の扱い
アナライザでは、USING 句で指定されたカラムの共通スーパータイプを決定するルールが標準化され、より予測可能な結果が得られるようになりました。特に、LowCardinality や Nullable のような型修飾子を扱う場合にその傾向が顕著です。
LowCardinality(T)とT: 型LowCardinality(T)のカラムを型Tのカラムと JOIN した場合、結果の共通スーパータイプはTとなり、LowCardinality修飾子は実質的に破棄されます。Nullable(T)とT: 型Nullable(T)のカラムを型Tのカラムと JOIN した場合、結果の共通スーパータイプはNullable(T)となり、Nullable の性質が保持されます。
id の共通スーパータイプは String と判定され、t1 の LowCardinality 修飾子は無視されます。
PROJECTIONのカラム名に関する変更
PROJECTION名の計算時には、別名は展開されません。24.3 より前のバージョンでは、2番目のカラムは展開された別名に基づいて命名されていました。
互換性のない関数引数の型
アナライザでは、型推論はクエリ分析の初期段階で行われます。 この変更により、型チェックは短絡評価の前に行われるため、if 関数の引数は常に共通のスーパータイプを持っている必要があります。
たとえば、次のクエリは There is no supertype for types Array(UInt8), String because some of them are Array and some of them are not というエラーで失敗します。
異種クラスター
アナライザによって、クラスター内のサーバー間通信プロトコルが大きく変更されます。そのため、アナライザを使用するかどうかが一致していないサーバー間では、分散クエリを実行できません。これは、26.9 より古いサーバーで構成されるクラスターの場合、enable_analyzer 設定の値が異なるサーバーを意味します。
バージョン 26.10 以降のサーバーには他のクエリ解析手段が残っていないため、古いイニシエーターが送信した値は無視され、常にアナライザでクエリが解析されます。2 つの解析方式では結果カラムの名前の付け方が異なり、イニシエーターは分片が返した Block をカラム名で対応付けるため、このようなクエリはイニシエーター側で NOT_FOUND_COLUMN_IN_BLOCK により失敗する可能性があります。例えば、非正規な大文字小文字表記で書かれた関数 (hostname()) を選択した場合、アナライザはそれを正規名 (hostName()) に解決します。したがって、古いクエリ解析で稼働しているクラスターでは、いずれかのサーバーを 26.10 にアップグレードする前に、すべてのサーバーで enable_analyzer = 1 を設定する必要があります。
サポートされていない機能
現在アナライザがサポートしていない機能は、以下のとおりです。- Annoy 索引。
- Hypothesis 索引。こちらで実装が進められています。
Cloud 移行
新たな機能とパフォーマンスの最適化をサポートするため、現在無効になっているすべてのインスタンスでアナライザを有効化しています。この変更により SQL のスコープ規則がより厳格になり、準拠していないクエリはお客様側で手動で更新する必要があります。移行ワークフロー
normalized_query_hashでsystem.query_logをフィルタリングし、クエリを特定します。
- アナライザを有効にしてクエリを実行します。その際、クエリが依存している場合は、旧来の解析における識別子解決を復元する互換性設定を追加します。
- クエリを見直して結果を検証し、移行前にそのクエリが生成していた出力と一致することを確認します。
不明な式識別子
エラー:Unknown expression identifier ... in scope ... (UNKNOWN_IDENTIFIER). 例外コード: 47
原因: フィルター内で計算済みの別名を参照する、曖昧なサブクエリの投影、「動的」な CTE スコープを使うといった、非標準で緩い従来の動作に依存するクエリは、現在では無効として正しく判定され、即座に拒否されます。
解決策: SQL を次のように修正してください。
- フィルター条件: 結果に対して絞り込む場合は、条件を WHERE から HAVING に移します。元データに対して絞り込む場合は、WHERE 句に同じ式を明示的に記述します。
- サブクエリのスコープ: 外側のクエリで必要になるすべてのカラムを明示的に選択します。
- JOIN の結合キー: キーが別名の場合は、USING ではなく完全な式を指定した ON を使用します。
- 外側のクエリでは、その内部のテーブルではなく、サブクエリ/CTE 自体の別名を参照します。
GROUP BY における非集計カラム
エラー:Column ... is not under aggregate function and not in GROUP BY keys (NOT_AN_AGGREGATE). Exception code: 215
原因: 旧アナライザでは、GROUP BY 句に含まれていないカラムも SELECT できていました (多くの場合、任意の値が選ばれていました) 。アナライザは標準 SQL に従うため、SELECT するすべてのカラムは、集計関数を適用するか、グルーピングキーである必要があります。
解決策: カラムを any() または argMax() で囲むか、GROUP BY に追加してください。
HAVING 内の非集約カラム
エラー:Column ... is not under aggregate function and not in GROUP BY keys (NOT_AN_AGGREGATE)。Exception code: 215
原因: 以前のアナライザは、HAVING 内の非集約の AND 条件を暗黙的に WHERE へ移動し、集約前のフィルターとして扱っていました。アナライザは Standard SQL に従うため、HAVING で参照できるのは集約キーと集約関数のみです。
解決策: 述語を手動で HAVING から WHERE に移すか、analyzer_compatibility_allow_non_aggregate_in_having = 1 (ClickHouse 26.7 以降で利用可能) を有効にして、移行を補助するためにレガシーな書き換えを復元してください。この互換性設定は、WITH CUBE、WITH ROLLUP、WITH TOTALS、GROUPING SETS では無視されます。集約、grouping、または非決定論的関数を含む条件は HAVING に残ります。いずれかの条件にウィンドウ関数または状態を持つ関数 (たとえば rowNumberInBlock) が含まれる場合、書き換えは HAVING 全体で無効になり、レガシーの動作と一致します。
CTE 名の重複
エラー:CTE with name ... already exists (MULTIPLE_EXPRESSIONS_FOR_ALIAS)。Exception code: 179
原因: 旧アナライザでは、同じ名前の共通テーブル式 (WITH …) を複数定義でき、後の定義によって前の定義が隠されていました。新しいアナライザは、デフォルトでこのような曖昧な定義を拒否します。
解決策: 重複している CTE をリネームし、名前が一意になるようにしてください。移行を支援する手段として、analyzer_compatibility_allow_cte_redefinition = 1 (ClickHouse 26.10 以降で利用可能) を有効にすると、レガシーな動作を復元できます。この場合、参照は同名の定義のうち、その時点で解決中ではない最新の定義に束縛されます。そのため、再定義からは直前の定義を読み取ることができ、クエリのボディからは最後の定義が読み取られます。
制限事項: MATERIALIZED として宣言された CTE と、WITH RECURSIVE 句内の CTE は、この設定を有効にしても再定義できません。また、旧アナライザと動作が異なるケースが 1 つあります。同じ名前の 2 つの定義の間で宣言された CTE も最後の定義に束縛されます。一方、旧アナライザでは、その CTE の宣言位置から参照できる定義に束縛されていました。
曖昧なカラム識別子
エラー:JOIN [JOIN TYPE] ambiguous identifier ... (AMBIGUOUS_IDENTIFIER) Exception code: 207
原因: クエリで、どのテーブルのものかを指定せずに、JOIN 内の複数のテーブルに存在するカラム名を参照しています。古いアナライザは内部ロジックに基づいてカラムを推測することがよくありましたが、アナライザでは明示的に名前を指定する必要があります。
解決策: table_alias.column_name のように、カラムを完全修飾してください。
FINAL の無効な使用
エラー:Table expression modifiers FINAL are not supported for subquery... または Storage ... doesn't support FINAL (UNSUPPORTED_METHOD)。例外コード: 1, 181
原因: FINAL はテーブルストレージ (特に [Shared]ReplacingMergeTree) の修飾子です。アナライザは、次の対象に FINAL を適用すると拒否します。
- サブクエリまたは派生テーブル (例: FROM (SELECT …) FINAL) 。
- FINAL をサポートしていないテーブルエンジン (例: SharedMergeTree) 。
countDistinct() 関数の大文字・小文字の区別
エラー: Function with name countdistinct does not exist (UNKNOWN_FUNCTION)。Exception code: 46
原因: 関数名では大文字・小文字が区別されるか、アナライザで厳密にマッピングされます。countdistinct (すべて小文字) は、今後は自動的に解決されません。
対処法: 標準の countDistinct (camelCase) または ClickHouse 固有の uniq を使用してください。