このトピックでは、EXPLAIN
コマンドを実行して実行計画をクエリする方法について説明し、LogicalView
、Gather
、MergeSort
などの基本演算子を紹介します。 Join、Agg、Sortなどのその他の演算子については、フォローアップのトピックで個別に説明します。
背景情報
通常、SQLチューニングには次の2つの手順が必要です。
- 問題を分析します。 たとえば、問題を分析するには、
EXPLAIN
コマンドを実行して実行計画を表示します。また、EXPLAIN analyze
を使用して実際の実行ステータスを表示することもできます。 詳細については、「クエリ実行プログラムの概要」をご参照ください。 ヒント
を使用してオプティマイザの動作を制御し、実行計画を変更します。
実行計画とEXPLAIN
コマンド
次の例では、EXPLAIN
コマンドを実行してクエリの実行計画を取得する方法について説明します。
EXPLAIN
の構文は次のとおりです。
ヒント
はEXPLAIN
の隣に配置する必要があります。EXPLAIN <SQL文>
EXPLAIN <ヒント> <SQL文>
このトピックのすべての例は、次のスキーマに基づいています。
テーブル 'sbtest1' の作成 (
'id' INT(10) UNSIGNED NOT NULL、
'k' INT(10) 未署名NOT NULLデフォルト '0' 、
'c' CHAR(120) NOT NULL DEFAULT ''、
'pad'CHAR (60) NOT NULL DEFAULT ''、
キー 'xid' ('id') 、
キー 'k_1 ' ('k')
) dbpartition BY HASH ('id') tbpartition BY HASH ('id') tbpartitions 4
次のEXPLAIN
コマンドを実行すると、PolarDB-X 1.0は対応する実行プランを返します。
mysql> explain select a.k、count(*) cnt from sbtest1a、sbtest1bここでa.id = b.kおよびa.id > 1000を有するkによるcntグループ> 1300によるcnt limit 5、10;
+ --------------------------------------------------------------------------------------------------------------------------------------------------- +
| ローカルプラン |
+ --------------------------------------------------------------------------------------------------------------------------------------------------- +
| MemSort(sort="cnt ASC", offset=? 2、fetch=? 3) |
| フィルター (条件="cnt > ? 1 ") |
| HashAgg(group="k", cnt="COUNT()") |
| BKAJoin(id="id" 、k="k" 、c="c" 、pad="pad" 、id0="id0" 、k0="k0" 、c0="c0" 、pad0="pad0" 、condition="id = k" 、type="inner" |)
| MergeSort(sort="k ASC") |
| LogicalView(tables="[0000-0031].sbtest1_[000-127]" 、shardCount=128、sql="SELECT * FROM 'sbtest1' WHERE ('id' > ?) ORDER BY 'k'") |
| 収集 (同時=true) |
| LogicalView(tables="[0000-0031].sbtest1_[000-127]", shardCount=128, sql="SELECT * FROM 'sbtest1' WHERE (('k' > ?)) AND ('k' IN ('?')))") |
| HitCache:false |
+ --------------------------------------------------------------------------------------------------------------------------------------------------- +
セットの9行 (0.01秒)
実行計画に加えて、EXPLAIN
の結果にはいくつかの追加情報が含まれています。 上記の例では、プランキャッシュがヒットしたかどうかを示すHitCache
のみが追加情報として含まれています。 詳細な原則については、「実行計画の管理」をご参照ください。
オペレーターの概要
PolarDB-X 1.0は、次の演算子をサポートしています。
意味 | 物理演算子 |
クエリの配信 | LogicalView 、LogicalModifyView 、およびPhyTableOperation |
参加 | BKAJoin 、NLJoin 、HashJoin 、SortMergeJoin 、HashSemiJoin 、SortMergeSemiJoin 、およびMaterializedSemiJoin |
ソート | MemSort とTopN |
集計 (グループ別) | HashAgg とSortAgg |
データ交換 | 収集 とMergeSort |
その他 | Project 、Filter 、Limit 、Union 、Window |
以下のセクションでは、演算子の一部の意味と実装について説明します。 残りの演算子については、フォローアップのトピックで説明します。
LogicalView
LogicalView
演算子は、データソースとして機能するストレージレイヤーMySQLからデータを取得します。 LogicalViewは、他のデータベースのTableScanまたはIndexScanに似ていますが、より多くのプッシュダウン操作をサポートします。 LogicalView
には、プッシュダウンされたSQL文とデータソース情報が含まれており、ビューに似ています。 プッシュダウンされるSQLステートメントには、Project、Filter、aggregation、sorting、Join、サブクエリなど、複数の種類の演算子が含まれる場合があります。 次の例は、EXPLAIN
コマンドのLogicalView
の出力情報と意味を示しています。
> explain select * sbtest1からid > 1000;
収集 (concurrent=true)
LogicalView(tables="[0000-0031].sbtest1_[000-127]" 、shardCount=128、sql="SELECT * FROM 'sbtest1' WHERE ('id' > ?)")
LogicalView
の情報は3つの部分で構成されています。
tables
: ストレージレイヤーMySQLに対応するテーブル名。 tablesパラメーターの値は、ピリオド (.) で分割されます。 ピリオドの前の情報 (.) は、データベースシャーディングに対応するIDを指定し、ピリオドの後の情報 (.) は、テーブル名とそのIDを指定します。 たとえば、[000-127]
は、テーブル名IDが000〜127のすべてのテーブルを示します。shardCount
: アクセスするテーブルシャーディングの総数。 この例では、IDが000から127の範囲の128テーブルシャーディングがアクセスされます。sql
: ストレージ層MySQLに配信されるSQLテンプレート。PolarDB-X 1.0実行中、PolarDB-X 1.0はテーブル名を物理テーブルの名前に置き換え、パラメーター化された定数疑問符 (?) を実際のパラメーターに置き換えます。 詳細については、「実行プランの管理」をご参照ください。
収集
収集
は、複数のデータセットを1つのデータセットにマージします。 上記の例では、Gather
演算子は、すべてのテーブルシャーディングから取得したデータを1つのデータセットにマージします。
並列クエリが無効になっている場合、Gather
演算子は通常LogicalView
の上に表示されます。 これは、Gather演算子がすべてのテーブルシャーディングのデータを収集してマージすることを示します。 並列クエリが有効になっている場合、Gather
演算子をより高い位置に引き上げることができます。 この場合、Gather
演算子はすべてのWorkerの計算結果を収集してマージします。
Gather
演算子のconcurrent
パラメーターは、サブ演算子を同時に実行するかどうかを指定します。 デフォルト値はtrue
です。 これは、データが同時にプルされることを示す。 並列クエリが有効になっている場合、プルアップされるGather
演算子の属性が変更され、parallel=true
と表示されます。
MergeSort
MergeSort
は、順序付きデータストリームを1つの順序付きデータストリームにマージおよびソートするマージソート演算子です。 例:
> explain select * from sbtest1 where id > 1000 order by id limit 5,10;
MergeSort(sort="id ASC", offset=? 1、fetch=? 2)
LogicalView(tables="[0000-0031].sbtest1_[000-127]", shardCount=128, sql="SELECT * FROM 'sbtest1' WHERE ('id' > ?) ORDER BY 'id' LIMIT (?? + ?)")
MergeSort
演算子は、次の3つの部分で構成されます。
sort
: 並べ替えフィールドと並べ替え順序。id ASC
はIDフィールドによる昇順のソートを示し、DESC
は降順のソートを示します。offset
: 結果セットが取得されたときのオフセット。 この例の値はパラメータ化されています。 実際の値は5です。fetch
: 返されるデータ行の最大数。 このパラメーターの値はパラメーター化されています。 これは、オフセットパラメータの値と同様である。 実際の値は10です。
プロジェクト
Project
: 投影操作。 つまり、入力データから一部の列を選択して出力したり、一部の列を変換 (関数や式で計算) して出力したりする。 Project演算子には定数を含めることもできます。
> explain select 'Hello, DRDS', 1 / 2, CURTIME();
プロジェクト (Hello, DRDS="_UTF-16 'Hello, DRDS'", 1 / 2="1/2", CURTIME()="CURTIME()")
Project
演算子のプランには、各列の名前と、対応する列、値、関数、または式が含まれます。
フィルター
Filter
演算子は、フィルタリング操作を示し、いくつかのフィルタ条件を含みます。 この演算子は入力データをフィルタリングします。 データが条件を満たす場合、データは出力として返されます。 そうでなければ、データは破棄される。 次の複雑な例には、前述の演算子のほとんどが含まれます。
> sbtest1からk、avg(id) avg_idを選択すると説明します。id > 1000> 1300を持つkによってグループ化されます。フィルター (条件="avg_id > ? 1 ")
プロジェクト (k="k", avg_id="sum_pushed_sum / sum_pushed_count")
SortAgg(group="k", sum_pushed_sum="SUM(pushed_sum)", sum_pushed_count="SUM(pushed_count)")
MergeSort(sort="k ASC")
LogicalView(tables="[0000-0031].sbtest1_[000-127]" 、shardCount=128、sql="SELECT 'k' 、SUM('id') AS 'pushed_sum' 、COUNT('id') AS 'pushed_count' FROM 'sbtest1' WHERE ('id'>) 'k' ORDER 'k'?
WHERE id > 1000
条件に対応するフィルター操作がない理由は、フィルター演算子がLogicalView
に押し下げられているためです。 LogicalView
のSQL文でWHERE (id > ?)
を表示できます。
Union AllとUnion Distinct
名前が示すように、Union AllはUNIONALL
に対応し、Union DistinctはUNIONDISTINCT
に対応します。 これらの演算子は通常2つ以上の入力を有する。 これは、演算子が複数の入力のデータをマージすることを示します。 例:
> explain select * From sbtest1 where id > 1000 union distinct select * From sbtest1 where id < 200;
UnionDistinct (同時=true)
収集 (concurrent=true)
LogicalView(tables="[0000-0031].sbtest1_[000-127]", shardCount=128, sql="SELECT * FROM 'sbtest1' WHERE ('id' > ?)")
収集 (concurrent=true)
LogicalView(tables="[0000-0031].sbtest1_[000-127]" 、shardCount=128、sql="SELECT * FROM 'sbtest1' WHERE ('id' < ?)")
LogicalModifyView
前のセクションでは、LogicalView
演算子が基になるデータソースからデータを取得することについて説明しました。 一方、LogicalModifyView
演算子は、基になるデータソースを変更します。 LogicalModifyViewは、SQLステートメントも記録します。 SQLステートメントは、INSERT
、UPDATE
、またはDELETE
です。
> update sbtest1 set c='Hello、DRS 'について説明します。id > 1000;
LogicalModifyView(tables="[0000-0031].sbtest1_[000-127]", shardCount=128, sql="UPDATE 'sbtest1' SET 'c' = ? どこ ('id' > ?)"
> sbtest1からの削除の説明id > 1000;
LogicalModifyView(tables="[0000-0031].sbtest1_[000-127]", shardCount=128, sql="DELETE FROM 'sbtest1' WHERE ('id' > ?)")
LogicalModifyView
のクエリプランの内容は、LogicalView
の内容と似ています。これには、配信された物理テーブルのシャーリング、テーブルのシャーリング数、SQLテンプレートが含まれます。 同様に、実行プランキャッシュが有効になっており、SQLステートメントがパラメータ化されているため、SQLテンプレートの定数は疑問符 (?
) に置き換えられます。
PhyTableOperation
PhyTableOperation
演算子は、物理テーブルシャーディングに対する操作を直接実行します。
> sbtest1値への挿入 (1、1、'1' 、'1') 、(2、2、'2' 、'2') について説明します。PhyTableOperation(tables="SYSBENCH_CORONADB_1526954857179TGMMSYSBENCH_CORONADB_VGOC_0000_RDS.[sbtest1_001]", sql="INSERT INTO? ('id' 、'k' 、'c' 、'pad') VALUES(? 、? 、? 、?)"、params=" 'sbtest1_001 '、1,1、1,1 ")
PhyTableOperation(tables="SYSBENCH_CORONADB_1526954857179TGMMSYSBENCH_CORONADB_VGOC_0000_RDS.[sbtest1_002]", sql="INSERT INTO? ('id' 、'k' 、'c' 、'pad') VALUES(? 、? 、? 、?)"、params=" 'sbtest1_002 '、2,2、2,2 ")
この例では、INSERT文は2行のデータを挿入します。 データの各行は、PhyTableOperation
演算子に対応します。 PhyTableOperation
演算子の内容は3つの部分で構成されています。
tables
: 物理テーブルの名前。 物理テーブルの名前は1つだけ指定されています。sql
: SQLテンプレート。 SQLテンプレートのすべてのテーブル名と定数はパラメータ化され、疑問符?
対応するパラメータは、後続のparams
パラメータで提供されます。params
: テーブル名と定数を含む、SQLテンプレートに対応するパラメーター。