ルールベースのパス選択後、複数のパスが選択可能な場合、OceanBaseデータベースは各パスのコストを計算し、その中からコストが最も小さいパスを最終的に選択します。
OceanBaseデータベースのコストモデルでは、CPUコスト(例えば、一つの述語を処理するためのCPU負荷)とI/Oコスト(例えば、マクロブロックやマイクロブロックの順次読み取りやランダム読み取りのコスト)が考慮されます。CPUコストとI/Oコストを合計して、総コストが求められます。
説明
複雑なSQLクエリにおいて、複数の MATCH ... AGAINST ... や他のフィルタ条件が含まれる場合、データベースはスキャン負荷を削減するために最適なインデックスパスを自動的に選択します。詳細については、MATCH AGAINST を参照してください。
OceanBaseデータベースでは、各アクセスパスのコストは実行計画に表示されます。以下の例を参照してください:
obclient> CREATE TABLE t1(a INT PRIMARY KEY, b INT, c INT, INDEX k1(b));
Query OK, 0 rows affected
/* 主表路径的代价*/
obclient>EXPLAIN SELECT/*+INDEX(t1 PRIMARY)*/ * FROM t1 WHERE b < 10;
+-----------------------------------------------------------------+
| Query Plan |
+-----------------------------------------------------------------+
| ===================================
|ID|OPERATOR |NAME|EST. ROWS|EST.TIME(us)|
-----------------------------------
|0 |TABLE SCAN|t1 |200 |622 |
===================================
Outputs & filters:
-------------------------------------
0 - output([t1.a], [t1.b], [t1.c]), filter([t1.b < 10]),
access([t1.b], [t1.a], [t1.c]), partitions(p0)
/* k1 路径的代价*/
obclient> EXPLAIN SELECT/*+INDEX(t1 k1)*/ * FROM t1 WHERE b < 10;
+--------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------+
| =====================================
|ID|OPERATOR |NAME |EST. ROWS|EST.TIME(us)|
-------------------------------------
|0 |TABLE SCAN|t1(k1)|200 |1114|
=====================================
Outputs & filters:
-------------------------------------
0 - output([t1.a], [t1.b], [t1.c]), filter(nil),
access([t1.b], [t1.a], [t1.c]), partitions(p0)
アクセスパスのコストは、主にアクセスパスのスキャンコストとテーブルへの再アクセスコストの2部分で構成されます。アクセスパスでテーブルへの再アクセスが不要な場合、再アクセスコストは発生しません。
OceanBaseデータベースでは、アクセスパスのコストは、スキャンされる行数、テーブルへの再アクセス行数、投影される列数、述語の数など、多くの要因に依存します。しかし、アクセスパスのコストは大きく行数に依存するため、以下の例では主に行数という観点からこれら2つのコスト部分を説明します。
アクセスパスのスキャンコスト
アクセスパスのスキャンコストはスキャンされる行数に比例します。理論上、スキャンされる行数が多いほど、実行時間は長くなります。アクセスパスにおいて、Query Rangeはスキャン範囲を決定し、それによってスキャンされる行数が決まります。Query Rangeのスキャンメカニズムは順次I/Oです。
テーブルへの再アクセスコスト
テーブルへの再アクセスコストは、再アクセス行数に正比例します。再アクセス行数が多いほど(再アクセス行数とは、インデックス上で実行可能なすべての述語を満たす行数のことです)、実行時間は長くなります。テーブルへの再アクセスのスキャンメカニズムはランダムI/Oであるため、テーブルへの再アクセスで1行をスキャンするコストは、Query Rangeで1行をスキャンするコストよりもはるかに高くなります。
アクセスパスのパフォーマンスを分析する際には、取得したQuery Rangeでスキャンされる行数とテーブルへの再アクセス行数に基づくことができます。これら2つの行数は通常、SQL文を実行することで取得できます。
以下の例のように、クエリ SELECT * FROM t1 WHERE c2 > 20 AND c2 < 800 AND c3 < 200 に対して、インデックス k1 のアクセスパスは、通常、Query Rangeを抽出するための述語を取得するためのプラン表示から始まります。述語 c2 > 20 AND c2 < 800 がQuery Rangeを抽出するために使用され、述語 c3 < 200 はテーブルへの再アクセス前の述語として扱われます。例の2つのクエリを使用して、Query Rangeで抽出される行数とテーブルへの再アクセス後の行数を確認できます。
obclient> CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT, c3 INT, c4 INT, c5 INT, INDEX k1(c2,c3));
Query OK, 0 rows affected
obclient> EXPLAIN EXTENDED_NOADDR SELECT/*+INDEX(t1 k1)*/ * FROM t1 WHERE
c2 > 20 AND c2 < 800 AND c3 < 200;
+--------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------+
| =====================================
|ID|OPERATOR |NAME |EST. ROWS|EST.TIME(us)|
-------------------------------------
|0 |TABLE SCAN|t1(k1)|156 |1216|
=====================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1], [t1.c2], [t1.c3], [t1.c4], [t1.c5]), filter([t1.c3 < 200]),
access([t1.c2], [t1.c3], [t1.c1], [t1.c4], [t1.c5]), partitions(p0),
is_index_back=true, filter_before_indexback[true],
range_key([t1.c2], [t1.c3], [t1.c1]), range(20,MAX,MAX ; 800,MIN,MIN),
range_cond([t1.c2 > 20], [t1.c2 < 800])
/* Query Range スキャンの行数 */
obclient> SELECT/*+INDEX(t1 k1)*/ COUNT(*) FROM t1 WHERE c2 > 20 AND c2 < 800;
+----------+
| count(*) |
+----------+
| 779 |
+----------+
1 row in set
/* テーブルへの再アクセスの行数 */
obclient> SELECT/*+INDEX(t1 k1)*/ COUNT(*) FROM t1 WHERE c2 > 20 AND c2 < 800
AND c3 < 200;
+----------+
| count(*) |
+----------+
| 179 |
+----------+
1 row in set