すべてのプロダクト
Search
ドキュメントセンター

PolarDB:コストベースのクエリ変換

最終更新日:Jul 03, 2024

このトピックでは、PolarDB for MySQLがコストベースのクエリ変換 (CBQT) を使用して複雑なクエリの実行効率を向上させる方法について説明します。

前提条件

  • 古いバージョンのクエリ変換

    クラスターはPolarDB for MySQL 8.0.2で、リビジョンバージョンは8.0.2.2.0以降です。

  • 新しいバージョンのクエリ変換

    クラスターはPolarDB for MySQL 8.0.2で、リビジョンバージョンは8.0.2.2.19以降です。

クラスターのバージョンを確認する方法については、「エンジンバージョンの照会」をご参照ください。

背景情報

クエリ変換とは、クエリステートメントを別の同等のクエリステートメントに変換するプロセスを指します。 次のサンプルのクエリ文を参照してください。

SELECT *
FROM d1
	JOIN f1 ON d1.c1 = f1.c1
	LEFT JOIN (
		SELECT d2.c2 AS d2_c2, f2.c3 AS f2_c3
		FROM d2, f2
		WHERE d2.c1 = f2.c1
	) derived
	ON derived.d2_c2 = d1.c2
		AND derived.f2_c3 = f1.c3;

クエリステートメントは、具体化されたテーブルのマージルールに基づいて、次のクエリステートメントに変更できます。

SELECT *
FROM d1
	JOIN f1 ON d1.c1 = f1.c1
	LEFT JOIN (d2
		JOIN f2 ON TRUE)
	ON d2.c1 = f2.c1
		AND f2.c3 = f1.c3
		AND d2.c2 = d1.c2;

MySQL Community Editionは、セマンティック変換が実行されるルールベースのクエリ変換のみをサポートします。 上記の例は、MySQL Community Editionによって実行される一般的なクエリ変換です。 しかしながら、このような変換は、場合によっては性能最適化をもたらさない。 上記のクエリステートメントを例にとると、d1f1、およびd2f2のインデックスが相関していない場合、d1およびf1の結合演算の出力の各行には、d2およびf2の個別の結合演算が必要です。 その結果、実行効率が著しく低下する。 したがって、クエリ変換、特に複雑な変換は、実行コストに基づいて実行されるべきである。 カーディナリティ、アクセス方法、結合順序などの要因が実行コストに影響を与える場合があります。 PolarDB for MySQLは、実行コストに基づいて特定の種類の変換を実行できるコストベースのクエリ変換をサポートしています。

複雑なクエリの場合、CBQTはすべての可能な変換メソッドを組み合わせて、状態空間と呼ばれるコレクションにします。 次に、CBQTは、クエリのコストが最も低い実行プランを選択します。 次の図では、コストベースのクエリ変換プロセスについて説明します。 CBQTは、変換方法AおよびBを収集し、状態空間において以下の組み合わせを生成する: なし (変換なし) 、A (変換Aのみ) 、B (変換Bのみ) 、およびAB (変換AおよびBの両方) 。 状態空間内の組み合わせは、それぞれ実行プランに対応する。 次いで、CBQTは、コストが最も低い実行計画を選択する。 この例では、変換Aに対応するプラン2が選択される。さらに、実行コストを節約することができる変換は、ルールベースのクエリ変換として定義される。 このような変換は、クエリ変換ルールが満たされる場合に実行される。

image

上記のクエリ文を例に取ります。 マテリアライズドテーブルのマージ後の実行計画を次の図に示します。

image

マテリアライズドテーブルのマージ前の実行計画を次の図に示します。

image

どのプランが最適であるかは、d2f2およびd1f1のインデックスが相関しているかどうか、および結合結果セットのサイズに依存する。 インデックスが関連付けられている場合、マージ後の実行計画は最適です。 そうでない場合、マージ前の実行計画は最適です。 CBQTフレームワークは、テーブルマージの前後の実行計画のコストを計算して比較します。 現在のシナリオで最適なプランが選択されます。

条件

ネストされたクエリとネストの深さ

ネストされたクエリは、別のクエリにネストされたクエリブロックです。 クエリブロックはサブクエリまたは内部クエリであり、外部クエリは親クエリまたは外部クエリです。 ネストの深さは、クエリのネストされたレイヤーの数であり、主にサブクエリと具体化されたテーブルを記述するために使用されます。 例:

SELECT * FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2 WHERE t2.c=t1.b);

入れ子の深さは2です。 親クエリはt1テーブルをクエリするクエリステートメントであり、サブクエリはt2テーブルをクエリするクエリステートメントです。

UNION文は、同じレイヤーのSQL文のみを結合します。 例:

SELECT *
FROM t1
WHERE t1.a IN (
	SELECT dt.b
	FROM (
		SELECT b, c
		FROM t2
		UNION
		SELECT b, c
		FROM t3
	) dt
	WHERE dt.c = t1.b
);

上記のクエリ文の入れ子の深さは3です。 dtテーブルのサブクエリは、UNION文を使用した同じレイヤーのSQL文の組み合わせです。

変革

背景情報のセクションで説明されている具体化されたテーブルマージなど、等価ルールに基づいてクエリを別の形式に変換するプロセス。

変換オブジェクト

[背景情報] セクションのマテリアライズドテーブルマージから派生したテーブルなど、同値ルールが適用されるオブジェクト。 異なる変換ルールが異なる変換オブジェクトに適用されます。 例えば、マテリアライズドテーブルマージの変換オブジェクトはマテリアライズドテーブルです。 サブクエリからSEMI JOIN文への変換の変換オブジェクトは、サブクエリです。

イテレーション

変換が実行される回数。 CBQTは、すべてのオブジェクトに対して可能なすべての変換を実行します。 変換が実行された後、いくつかのクエリブロックを再び変換することが可能である。 たとえば、サブクエリが具体化されたテーブルに変換された後、具体化されたテーブルマージルールを使用してテーブルを変換できます。 したがって、新しいオブジェクトに対して変換を実行する必要があります。 このプロセスは、CBQTの反復として知られている。 反復回数は、変換プロセスが繰り返し実行される回数である。

Usage

PolarDB for MySQLは、CBQTの2つのバージョンを提供します。 cbqt_enabledパラメーターを設定して、機能を有効または無効にします。 cbqt_versionパラメーターを設定して、cbqtのバージョンを指定します。 cbqt_versionが1に設定されている場合、古いバージョンが使用されます。 cbqt_versionが2に設定されている場合、新しいバージョンが使用されます。

パラメーター

レベル

説明

cbqt_enabled

グローバルとセッション

CBQTを有効または無効にします。 デフォルト値はONです。 有効な値:

  • オン

  • オフ

  • REPLICA_ON: 読み取り専用ノードでCBQTを有効にします。

cbqt_version

グローバルとセッション

CBQTのバージョンを指定します。 有効な値:

  • 1: 古いバージョンのCBQTを使用します。 デフォルト値です。

  • 2: CBQTの新しいバージョンを使用します。

両方のバージョンのパラメータの詳細な説明を参照してください。

CBQTの旧バージョン

CBQTは、最適な実行プランを選択するのに長い時間を費やすことがある。 短期間のクエリへの影響を避けるために、cbqt_cost_thresholdパラメーターを使用して、クエリのCBQTをトリガーするためのしきい値を指定できます。 CBQTは、クエリのコストがこのパラメーター値を超えた場合にのみトリガーされます。 MySQL Community EditionではなくPolarDBによって提供されるサブクエリの場合、CBQTに基づくGROUP by句を使用して脱相関が実行されます。 MySQL Community Editionで提供される変換については、コストに基づいて実行するかどうかを指定できます。 派生マージ機能は、polar_optimizer_switchパラメーターのderived_merge_cost_based変数によって制御されます。

パラメーター

レベル

説明

cbqt_cost_threshold

グローバルとセッション

クエリのCBQTをトリガーするためのしきい値。 CBQTは、クエリのコストがこのパラメーター値を超えた場合にのみトリガーされます。

有効な値: 0 ~ 18446744073709551615 デフォルト値:100000。

cbqt_timeout

グローバルとセッション

CBQTのタイムアウト期間。 最適な実行プランを見つけるのにかかる時間が指定された期間よりも長い場合、CBQTは最適なプランの検索を停止し、見つけた最適なプランを使用してクエリを実行します。

有効な値: 0 ~ 18446744073709551615 デフォルト値:200 単位:ミリ秒。

説明

値を0に設定した場合、タイムアウト期間は指定されません。

polar_optimizer_switch

グローバルとセッション

PolarDBのクエリ最適化機能を有効にするかどうかを指定します。 有効な値:

  • unnest_use_window_function: ウィンドウ関数を使用してサブクエリを相関解除するかどうかを指定します。 デフォルト値: ON。 有効な値:

    • ON

    • OFF

  • unnest_use_group_by: GROUP by句を使用してサブクエリを相関解除するかどうかを指定します。 このサブクエリ脱相関メソッドは、CBQTに基づいて実装されます。 デフォルト値: ON。 有効な値:

    • ON

    • OFF

  • derived_merge_cost_based: CBQTに基づいて派生マージ機能を実装するかどうかを指定します。 デフォルト値: OFF。 有効な値:

    • OFF

    • ON

CBQTの新バージョン

CBQTは、反復を実行し、最適な実行プランを選択するのに長い時間を費やし得る。 プロセスを制御する次のパラメーターを設定できます。

パラメーター

レベル

説明

cbqt_iteration_limit

グローバル

CBQTの反復回数。 繰り返し回数が多いほど、最適なプランを選択する可能性が高く、時間がかかることを示す。 反復回数が少ないほど、最適なプランを選択する可能性が低く、時間消費が少ないことを示す。

有効な値: 1 ~ 10。 デフォルト値は 1 です。

cbqt_max_nested_level

グローバルとセッション

CBQTが処理できるクエリ文の最大ネスト深さ。 クエリ文の入れ子の深さがこの値を超える場合、CBQTはクエリ文に実装されません。

有効な値: 1 ~ 64。 既定値:5

cbqt_search_strategy

グローバル

CBQTが最適なプランを選択するための戦略。 有効な値:

  • auto: アダプティブ検索。 デフォルト値です。 PolarDBは、変換するクエリに基づいて線形または2パス戦略を適応的に選択します。

  • linear: リニア検索。 この戦略が使用される場合、PolarDBは各クエリが異なるアプリケーションに変換される前後の実行コストを比較し、より良い実行計画を選択します。

  • twoPass: 2パス検索。 この戦略を使用すると、PolarDBは、すべてのクエリが同じアプリケーションに変換された場合、またはすべてのクエリが変換されていない場合の実行コストを比較し、より適切な実行計画を選択します。

cbqt_rule_switch

グローバルとセッション

クエリ最適化機能を有効にするかどうか、およびクエリ変換を実行するかどうかを指定します。 有効な値:

  • merge_derived: コストベースのマテリアライズドテーブルのマージを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • subquery_to_derived: サブクエリからマテリアライズドテーブルへのコストベースの変換を有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • unnest_subquery_by_groupby: GROUP by句を使用してコストベースの脱相関を有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • unnest_subquery_by_windows: ウィンドウ関数を使用してデコリレーションを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • derived_projection_pruning: マテリアライズドテーブルのプロジェクションのプルーニングを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • cond_pushdown: 条件pushdownを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • heuristic_merge_derived: ヒューリスティックマテリアライズドテーブルのマージを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • subquery_to_semijoin: サブクエリからSEMI JOINへの変換を有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • heuristic_coalesce_subquery: ヒューリスティックサブクエリの折りたたみを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF

  • coalesce_subquery: コストベースのサブクエリフォールディングを有効にするかどうかを指定します。 デフォルト値: ON。

    • ON

    • OFF