5 億 5000 万行のテーブルにインデックス構成テーブル (IOT) を使用しています。主キーは、他の 2 つのテーブルに対する外部キーでもある 2 つの列 (id1 と id2) で構成されます (table1 に対する id1 FK、table2 に対する id2 FK)。
IOT を使用する場合、Oracle のドキュメント ( http://docs.oracle.com/cd/B28359_01/server.111/b28310/tables012.htm#i1007389 ) によると、主キーのプレフィックスによる並べ替えは、主キーのサフィックス。実際、行は主キーとそれを構成する列の順序に従ってソートされます。
ただし、IOT を他の 2 つのテーブルと結合したときに取得した説明プランを次に示します。id1 または id2 のいずれかで注文しようとしています。id1でソートすることで、より良いコストが得られると予想していました。しかし、そうではありません。
id1 に使用される値は、table1 の合計 489000 行のうち 58000 行に対応します。id2 に使用される値は、table2 の合計 248900 行のうち 760 行に対応します。
SQL クエリ:
SELECT a.id1, a.id2, a.some_column
FROM iot_table a
INNER JOIN table1 t1 ON t1.id = a.id1
INNER JOIN table2 t2 ON t2.id = a.id2
WHERE t1.col_x = x AND t2.col_y = y
ORDER BY {a.id1|a.id2};
id1 による計画の順序を説明します。
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 11243 (100)| |
| 1 | NESTED LOOPS | | 1311K| 42M| 11243 (1)| 00:01:44 |
| 2 | MERGE JOIN CARTESIAN | | 46M| 842M| 11173 (1)| 00:01:43 |
|* 3 | TABLE ACCESS BY INDEX ROWID | TABLE1 | 58152 | 511K| 4745 (1)| 00:00:44 |
| 4 | INDEX FULL SCAN | TABLE1_ID1_IDX | 488K| | 15 (0)| 00:00:01 |
| 5 | BUFFER SORT | | 799 | 7990 | 6429 (1)| 00:01:00 |
| 6 | TABLE ACCESS BY INDEX ROWID| TABLE2 | 799 | 7990 | 1 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | TABLE2_COL_Y_IDX | 799 | | 1 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | IOT_TABLE_PK | 1 | 15 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------
id2 による計画の順序を説明します。
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5159 (100)| |
| 1 | NESTED LOOPS | | 1311K| 42M| 5159 (2)| 00:00:48 |
| 2 | MERGE JOIN CARTESIAN | | 46M| 842M| 5089 (1)| 00:00:47 |
|* 3 | TABLE ACCESS BY INDEX ROWID | TABLE2 | 799 | 7990 | 2512 (1)| 00:00:24 |
| 4 | INDEX FULL SCAN | TABLE2_ID2_IDX | 248K| | 28 (0)| 00:00:01 |
| 5 | BUFFER SORT | | 58152 | 511K| 2577 (2)| 00:00:24 |
| 6 | TABLE ACCESS BY INDEX ROWID| TABLE1 | 58152 | 511K| 3 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | TABLE1_COL_X_IDX | 58152 | | 1 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | IOT_TABLE_PK | 1 | 15 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------
行は主にこの列に従ってソートする必要があり、オラクルは IOT B*-Tree をそのまま参照する必要があるのに、なぜ id1 でソートするとコストが最悪になるのか疑問に思っています。
ご協力ありがとうございました
私は Oracle 11.2 g を使用しており、統計は最新です。