2021.11.19
SQLチューニングにDictionary Viewを活用する – Part2
SQLチューニングにDictionary Viewを活用する – Part2
エクセムコンサルティング本部/DBコンサルティングチームチョンドン
概要
SQLパフォーマンスを向上させるためには、判断できる根拠を収集することが重要です。
SQLに使用されている関連テーブル情報とインデックス情報を収集して総合的に判断しなければ、より効率的な性能改善を導き出すことができないからです。
Oracleは、これらの情報をDictionary Viewを介してユーザーに伝えています。
その中で、今回のホワイトペーパーでは、テーブルとインデックス関連情報をもとにSQLのパフォーマンス改善にどのように活用されるかを述べています。
テーブル、インデックス統計活用改善事例
テーブルとインデックスに関する情報は、Dictionary Viewを通して見ることができます。
OracleはDBA_TABLES、DBA_TAB_COLUMNS、DBA_INDEXES、DBA_IND_COLUMNS、
DBA_IND_EXPRESSIONSのViewを通じて関連情報を検索活用できるように提供しています。
テストを通してそのViewがどのように活用されるかを調べてみましょう。
インデックス 効率 判定 ケース
SELECT c1 ,
c2 ,
c3 ,
c4 ,
c5 , c6
FROM dict_view_t1 t WHERE c2 = ‘B’
AND c3 = ’11’
AND c4 = ‘RED’
AND c5 = ‘1981’
AND C1 = 1
————————————————————————————-
|Id |Operation |Name |Starts|E-Rows |A-Rows | A-Time |
————————————————————————————-
| 0 |SELECT STATEMENT | | 1 | | 1 |00:00:00.02 |
|* 1 |TABLE ACCESS FULL|DICT_VIEW_T1 | 1 | 1 | 1 |00:00:00.02 |
————————————————————————————-
対応するSQLの実行計画を見ますと、総抽出件数が1件と非常に少ないですが、TABLE FULL SCANを介して情報を抽出しているので効率的かどうかを判断する必要性があります。
もしそうなら、TABLE FULL SCANが効率的かどうか、そうでなければそのTABLEに適したインデックスが存在するのか、インデックスが存在すればどのようなインデックスが効率的であるかを考えなければならなりません。
Oracleは、関連するDictionary Viewを介してそのデータを提供しています。
まず、テーブルインデックスの存在は、NDEXES DBA_Iによって決定できます。
[Script 3 実行結果]
INDEX_NAME U TABLESPACE DISTINCT CLUSTERING FACTOR BLEVEL LEAF_BLK
————————— – ———- ——— —————— —— ———
DICT_VIEW_T1_IDX_01(SH) | N USERS | 1000000 | 3377 | 2 | 2226 |
DICT_VIEW_T1_IDX_02(SH) | N USERS | 10 | 33770 | 2 | 3540 |
また、その索引の構成列情報は、DBA_IND_COLUMNSを介して調べることができます。
[Script 4 実行結果]
INDEX_NAME TYPE U COLUMN LIST
——————– —- — ————– DICT_VIEW_T1_IDX_01 NORM N C1
DICT_VIEW_T1_IDX_02 NORM N C2, C3, C4, C5
そして、インデックス構成列のCARDINALITYやDISTINCT VALUEなどを調べるには
DBA_TABLESとDBA_TAB_COLUMNSを介して関連情報を取得できます。
- CARDINALITY = ( DBA_TABLES.NUM_ROWS – DBA_TAB_COLUMN.NUM_NULLS ) / DBA_TAB_COLUMNS.NUM_DISTINCT
[Script 1結果を利用する]
TABLE NAME TABLESPACE NAME NUM_ROWS DEGREE BLOCKS
—————- ————— ——– —— ——
DICT_VIEW_T1(SH) USERS 1000000 1
3439
[活用 Script 2 結果]
COLUMN_NAME DATA_TYPE DATALEN NN DISTINCT DENSITY NUM_NULLS BUCKET SAMPLE_SIZE
———— ——– ———- — ——— ———– ———- —— ———-
C1 | NUMBER | 22 | N | 1000000 | 0.000001000 | 0 | 1 | 1000000 |
C2 | VARCHAR2 | 1 | Y | 2 | 0.500000000 | 0 | 1 | 1000000 |
C3 | NUMBER | 22 | Y | 10 | 0.100000000 | 0 | 1 | 1000000 |
C4 | VARCHAR2 | 5 | Y | 5 | 0.200000000 | 0 | 1 | 1000000 |
C5 | NUMBER | 22 | Y | 10 | 0.100000000 | 0 | 1 | 1000000 |
これにより、Dictionary Viewを介して関連情報が提供されます。
私たちはこれらの情報を活用して性能問題を改善するための判断根拠とすることができます。
それでは、そのSQLの関連情報を活用して効率を判断してみましょう。
まず、SQLのWHERE条件句を見てみると、検索条件としてC1~C5まで存在します。
また、TABLE DICT_VIEW_T1には2つのインデックスが存在することをDictionary Viewを通じて確認できます。
まず、2つのインデックスDICT_VIEW_T1_IDX_01、DICT_VIEW_T1_IDX_02のうちどのインデックスが効率的かを判断しましょう。
インデックスDICT_VIEW_T1_IDX_01は列C1で構成されています。
C1のCARDINALITYを見ると(1000000 – 0)/ 1000000 = 1で非常に効率的であることがわかります。
つまり、TABLE DICT_VIEW_T1のNUM_ROWS値が1000000で、インデックスDICT_VIEW_T1_IDX_01のDISTINCT値が1000000なので、インデックス平均抽出件数が(1000000/1000000 = 1)約1件。
今回はインデックスDICT_VIEW_T1_IDX_02の効率を確認してみましょう。 DICT_VIEW_T1_IDX_02の構成列はC2、C3、C4、C5で構成されています。
インデックス DICT_VIEW_T1_IDX_02 構成列の各 CARDINALITY は C2 =(10000000 – 0) / 2 = 5000000, C3 = (10000000 – 0) / 10 =
1000000、C4 = (10000000 – 0) / 5 = 2000000、C5 = (10000000 – 0) / 10 = 1000000
です。インデックスDICT_VIEW_T1_IDX_02構成列のCARDINALITYは、C1列と比較して非常に非効率的であることが確認できます。
つまり、TABLEのNUM_ROWS値が1000000で、インデックスDICT_VIEW_T1_IDX_02のDISTINCT値が10なので、1000000/10 = 100000です。
インデックス平均抽出件数が約100000件で効率的ではないことが確認できます。
つまり、インデックスDICT_VIEW_T1_IDX_01がはるかに効率的であると判断できます。
それでは、実際にそうなのかDATAを通して確認してみましょう。
SELECT COUNT( * ) TOTAL_ROWS,
COUNT( DISTINCT c1 ) COL_NDV—インデックスDICT_VIEW_T1_IDX_01 の構成列です
FROM dict_view_t1
TOTAL_ROWS COL_NDV
———- ——- 1000000 1000000
DICT_VIEW_T1_IDX_01を活用する際に実際のDATAを見ると、TABLE総ROW数1000000、インデックス構成列C1のDISTINCT値1000000なので、C1条件で検索する場合、インデックスによる平均抽出件数が1件であると予測できます。
同じ結果を示すことを確認することができます。
SELECT COUNT( * ) TOTAL_ROWS,
COUNT( DISTINCT c2||c3||c4||c5 ) インデックス DICT_VIEW_T1_IDX_02の構成コラムをCOL_NDV—します
FROM dict_view_t1
TOTAL_ROWS COL_NDV
———- ——- 1000000 10
DICT_VIEW_T1_IDX_02 活用時に実際のDATAを見ると、TABLE総ROW数1000000、インデックス構成列C2、C3、C4、C5のDISTINCT値が10なので、C2、C3、C4、C5条件で検索する場合、インデックスによる平均抽出件数を予測することができ、Dictionary Viewで見たのと同じ結果を示すことが確認できます。 つまり、インデックスDICT_VIEW_T1_IDX_01を使用するときに1回のTABLE RANDOM ACCESS、
DICT_VIEW_T1_IDX_02を使用すると最大100000回のTABLE RANDOM ACCESSが発生します。
そのため、DICT_VIEW_T1_IDX_01がはるかに効率的であると判断できます。
最後に、そのインデックスを活用して実際の実行計画を見てみましょう。
SELECT c1 ,
c2 ,
c3 ,
c4 ,
c5 , c6
FROM dict_view_t1 t WHERE c2 = ‘B’
AND c3 = ’11’
AND c4 = ‘RED’
AND c5 = ‘1981’
AND c1 = 1
—————————————————————————————-
|Id |Operation |Name |A-Rows | A-Time |Buffers |
—————————————————————————————-
|0 |SELECT STATEMENT | | 1 |00:00:00.01 | 4 |
|* 1 |TABLE ACCESS BY INDEX ROWID|DICT_VIEW_T1 |1 |00:00:00.01 | 4 |
|* 2 |INDEX RANGE SCAN |DICT_VIEW_T1_IDX_01 | 1 |00:00:00.01 | 3 |
—————————————————————————————-
インデックスDICT_VIEW_T1_IDX_01を活用したSQLの実行計画です。
インデックスから1件を抽出した後、1回のTABLE RANDOM ACCESSが発生し、合計4BLOCKSをREADしています。
インデックス構成カラムC1がUNIQUEなので、インデックスBLOCK READS量も非常に少ないことがわかります。
SELECT c1 ,
c2 ,
c3 ,
c4 ,
c5 , c6
FROM dict_view_t1 t WHERE c2 = ‘B’
AND c3 = ’11’
AND c4 = ‘RED’
AND c5 = ‘1981’
AND c1 = 1
—————————————————————————————-
|Id |Operation |Name |A-Rows | A-Time | Buffers |
—————————————————————————————-
| 0 |SELECT STATEMENT | | 1 |00:00:00.09 | 3715 |
|* 1 |TABLE ACCESS BY INDEX ROWID|DICT_VIEW_T1 | 1 |00:00:00.09 | 3715 |
|* 2 | INDEX RANGE SCAN |DICT_VIEW_T1_IDX_02 | 100K |00:00:00.89 | 338|
—————————————————————————————-
- CLUSTERING FACTOR は33770であるため、30 個の ROW ごとに約 30 個の TABLE RANDOM ACCESSが削減されるため、BLOCK READS の量が減少します
インデックスDICT_VIEW_T1_IDX_02を活用したSQLの実行計画です。
インデックスから100000件を抽出した後、約3715-338 = 3377のTABLE RANDOM ACCESSが発生し、合計3715 BLOCK READSが発生し、インデックスBLOCK READS量もDICT_VIEW_T1_IDX_01に比べて非効率的です。
合計3つのSQL実行計画をまとめてみると、最初のTABLE FULL SCANした場合は合計3348 BLOCK、2番目のインデックスDICT_VIEW_T1_IDX_01を活用した場合はインデックス3 BLOCK READS、1回のTABLE RANDOM ACCESS、3番目のDICT_VIEW_T1した場合、インデックス338 BLOCK READSと約3377回のTABLE RANDOM ACCESSが発生しています。
つまり、Dictionary Viewで見た結果と同様に、インデックスDICT_VIEW_T1_IDX_01を活用したときに最も効率的であることを実際の実行計画を通じて確認することができます。
テーブル、インデックス Dictionary View の詳細な説明と活用スクリプト
上記の改善事例から分かるように、Dictionary ViewにはSQL性能を改善するための判断材料として有用なViewが存在します。
DBA_TABLES、DBA_TAB_COLUMNS、DBA_INDEXES、DBA_IND_COLUMNS、DBA_IND_EXPRESSIONSなどを活用して、パフォーマンス向上に有用に使用することができます。
本説明のDictionary Viewのバージョンは11g R2バージョンです。
TABLE、INDEX関連のDBA_*VIEW
SQLパフォーマンスの問題に役立つTABLE、INDEX関連のDictionary ViewであるDBA_TABLES、
DBA_TAB_COLUMNS、DBA_INDEXES、DBA_IND_COLUMNS、DBA_IND_EXPRESSIONS
について詳しく学びましょう。
DBA_TABLES
DBA_TABLESは、データベース内のすべてのTABLEに関する情報を記述したVIEWです。
このViewの重要な列情報は[表1]のとおりです。
Column Name | Data Type | Descrption |
OWNER | VARCHAR2(30) | TABLE の OWNER |
TABLE_NAME | VARCHAR2(30) | TABLE の名前 |
TABLESPACE_NAME | VARCHAR2(30) | TABLEが属するの TABLESAPCE 名 |
PCT_FREE | NUMBER | ブロックの 最小 空き 領域 (パーセント) |
PCT_USED | NUMBER | 予約するブロックの最小使用可能な スペース百値(百) スコア) |
NEXT_EXTENT | NUMBER | 次の拡張Size |
MIN_EXTENTS | NUMBER | セグメントが 許可する最小拡張数 |
NUM_ROWS* | NUMBER | TABLE ROW 数 |
BLOCKS* | NUMBER | TABLEの DATA BLOCK 数 |
DEGREE | NUMBER | TABLEを並列に処理する場合に使用するプロフェッショナルの数 |
PARTITIONED | VARCHAR2 | パーティションが TABLEかどうかを示します |
LAST_ANALYZED | DATE | 最後 の統計の 作成 日 |
AVG_SPACE | NUMBER | DATA BLOCK の平均フリースペース |
AVG_ROW_LEN | NUMBER | TABLE ROWの平均長さ(バイト単位) |
EMPTY_BLOCKS | NUMBER | TABLEの空のBLOCK 数 |
Script 1>
SELECT table_name||'(‘ ||owner||’)’ ||CHR( 10 ) ||tablespace_name
||decode( partitioned , ‘YES’ , ‘* Partitioned ‘ , ” )
||decode( TEMPORARY , ‘Y’ , ‘* Temporary ‘ , ” ) AS “TAB_INFO” , TRUNC( num_rows ) num_rows ,
avg_row_len ,
blocks ||CHR( 10 ) ||empty_blocks AS “BLK_INFO” , TRIM( degree ) degree ,
avg_space , chain_cnt ,
pct_free || ‘/’ ||pct_used || ‘/’ ||pct_increase pct , ini_trans || ‘/’ ||max_trans tran ,
decode( SIGN( FLOOR( initial_extent/1024/1024 ) ) , 1 , ROUND( initial_extent/1024/1024 )
||’m’ , ROUND( initial_extent/1024 ) ||’k’ ) || ‘/’
||decode( SIGN( FLOOR( next_extent/1024/1024 ) ) , 1 , ROUND( next_extent/1024/1024 )
||’m’ , ROUND( next_extent/1024 ) ||’k’ ) ||CHR( 10 ) ||min_extents ||’/’
||decode( max_extents , 2147483645 , ‘Unlimit’ , max_extents ) inext , FREELISTS || ‘/’ ||freelist_groups free ,
TO_CHAR( last_analyzed , ‘yyyy-mm-dd:hh24:mi:ss’ ) last_analFROM dba_tables WHERE table_name = UPPER( TRIM( :table_name ) )
AND owner = UPPER( TRIM( :schname ) )
[Scrpit 1]DBA_TABLES 使用率です
DBA_TAB_COLUMNS
DBA_TAB_COLUMNSは、データベース内のClusters、Tables、Viewsのすべての列情報です。
このViewの重要な列情報は[表2]のとおりです。
Column Name | Data Type | Descrption |
OWNER | VARCHAR2(30) | TABLE, VIEW, CLUSTER の OWNER |
TABLE_NAME | VARCHAR2(30) | TABLE、VIEW、および CLUSTER の名前 |
COLUMN_NAME | VARCHAR2(30) | COLUMNの名称です |
DATA_TYPE | VARCHAR2(106) | COLUMNの DATA TYPE |
DATA_LENGTH | NUMBER | COLUMN の 長さ(上 ) |
NULLABLE | VARCHAR2(1) | 空使用可能 |
NUM_DISTINCT | NUMBER | COLUMNの DISTINCT値(DATA 値の型) 数量) |
DENSITY | NUMBER | COLUMN における DENSITY 値 |
NUM_NULLS | NUMBER | COLUMNに含まれる空の数 |
SAMPLE_SIZE | NUMBER | 統計を収集するためのSAMPLE SIZE |
LAST_ANALYZED | DATE | 最後 の統計の 作成 日 |
HISTOGRAM | VARCHAR2 | ヒストグラムの TYPE(NONE、FREQUENCY、HEIFHT ) です BALANCED) |
Script 2 >
SELECT column_name ,
data_type , data_length ,
decode( data_precision || ‘/’ ||data_scale , ‘/’ , NULL , data_precision || ‘/’ ||data_scale ) dpds , nullable nn ,
num_distinct , density , num_nulls , num_buckets , sample_size ,
TO _CHAR ( last_ analyzed , ‘yyyy- mm – dd ‘ ) last _ FROM dba _ tab _ columns
WHERE owner = UPPER( TRIM( :schname ) )
AND table_name = UPPER( TRIM( :table_name ) )
[Scrpit 2] DBA_TAB_COLUMNSの活用
DBA_INDEXES
DBA_INDEXESには、データベースに存在するすべてのインデックス情報が含まれています。
列情報は[表3]の通りです。
Column Name | Data Type | Descrption |
OWNER | VARCHAR2(30) | インディーズ の OWNER |
INDEX_NAME | VARCHAR2(30 | INDEX の NAME |
INDEX_TYPE | VARCHAR2(27) | INDEXのTYPE (NORMAL, BITMAP, FUNCTION- ) 非会計基準など) |
TABLE_OWNER | VARCHAR2(30) | TABLEの OWNER 所有INDEX |
TABLE_NAME | VARCHAR2(30) | インディクス を所有するTABLEの名前 |
TABLE_TYPE | CHAR(5) | INDEX OBJECTのTYPE (NEXT OBJECT, INDEX, ) TABLE など) |
UNIQUENESS | VARCHAR2(9) | INDEXが UNIQUE OR NONUNIQUEであるかどうかを識別します |
TABLESPACE_NAME | VARCHAR2(30) | INDEXを含む TABLE SPACE 名 |
BLEVEL* | NUMBER | B-TREE レベル 値 |
LEAF_BLOCKS* | NUMBER | INDEXにおけるLEAF BLOCK数 |
DISTINCT_KEYS* | NUMBER | INDEXの DISTINCT 値 |
PARTITIONED | VARCHAR2(3) | INDEX のパーティション |
CLUSTERING_FACTOR | NUMBER | DATAが INDEX ORDER の順に集約される度合い 指示します |
NUM_ROW | NUMBER | INDEXのROWの総数です |
LAST_ANALYZED | DATE | 最後 の統計の 作成 日 |
Script 3 >
SELECT index_name||'(‘ ||owner||’)’index_name , SUBSTR( uniqueness , 1 , 1 ) u ,
tablespace_name||decode( partitioned , ‘YES’ , ‘*Partitioned ‘ , ” )
||decode( TEMPORARY , ‘Y’ , ‘*Temporary ‘ , ” ) TABLESPACE ,
TO_CHAR( TRUNC( num_rows ) ) ||chr( 10 ) ||to_char( distinct_keys ) AS “NUM_ROWS_DISTINCT” ,
clustering_factor ,
leaf_blocks ||CHR( 10 ) ||blevel AS “BLK_INFO” , avg_leaf_blocks_per_key || ‘/’ ||avg_data_blocks_per_key alb_adb , ini_trans || ‘/’ ||max_trans tran ,
decode( SIGN( FLOOR( initial_extent/1024/1024 ) ) , 1 , ROUND( initial_extent/1024/1024 )
||’m’ , ROUND( initial_extent/1024 ) ||’k’ ) || ‘/’ ||decode( SIGN( FLOOR( next_extent/1024/1024 ) ) ,
1 , ROUND( next_extent/1024/1024 ) ||’m’ , ROUND( next_extent/1024 ) ||’k’ ) ||CHR( 10 )
||min_extents ||’/’ ||decode( max_extents , 2147483645 , ‘unlimit’ , max_extents ) inext ,
FREELISTS || ‘/’ ||freelist _ groups free , TO _ CHAR ( last _ analyzed , ‘yyyy- mm – dd ‘ ) last _
FROM dba_indexes
WHERE table_name = UPPER( TRIM( :table_name ) ) AND table_owner = UPPER( TRIM( :schname ) )
[Script 3]DBA_I DBA_INDEXESを活用
DBA_IND_COLUMNS
DBA_IND_COLUMNS は、データベース内のClusters、Tables、Viewsのすべてのインデックス列
情報を含んでいます。
このViewの重要な列情報は[表4]のとおりです。
Column Name | Data Type | Descrption |
OWNER | VARCHAR2(30) | インディーズ の OWNER |
INDEX_NAME | VARCHAR2(30 | INDEX の NAME |
INDEX_TYPE | VARCHAR2(27) | INDEXのTYPE (NORMAL, BITMAP, FUNCTION- ) 非会計基準など) |
TABLE_OWNER | VARCHAR2(30) | INDEX OBJECT所有者(OWNER) |
COLUMN_POSITION | NUMBER | INDEX はCOLUMN の順序を設定します |
DESCEND | VARCHAR2 | SORT状態を示します |
Script 4 >
SELECT index_name ,
SUBSTR( index_type , 1 , 4 ) TYPE , SUBSTR( uniqueness , 1 , 1 ) u ,
(
SELECT MAX( decode( column_position , 1 , column_name ) ) ||
decode( MAX( decode( column_position , 2 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 2 , column_name ) ) ||
decode( MAX( decode( column_position , 3 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 3 , column_name ) ) ||
decode( MAX( decode( column_position , 4 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 4 , column_name ) ) ||
decode( MAX( decode( column_position , 5 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 5 , column_name ) ) ||
decode( MAX( decode( column_position , 6 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 6 , column_name ) ) ||
decode( MAX( decode( column_position , 7 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 7 , column_name ) ) ||
decode( MAX( decode( column_position , 8 , column_name ) ) , NULL ,
NULL , ‘, ‘ ) ||
MAX( decode( column_position , 8 , column_name ) ) ||
decode( MAX( decode( column_position , 9 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 9 , column_name ) ) ||
decode( MAX( decode( column_position , 10 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 10 , column_name ) ) ||
decode( MAX( decode( column_position , 11 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 11 , column_name ) ) ||
decode( MAX( decode( column_position , 12 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 12 , column_name ) ) ||
decode( MAX( decode( column_position , 13 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 13 , column_name ) ) ||
decode( MAX( decode( column_position , 14 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 14 , column_name ) ) ||
decode( MAX( decode( column_position , 15 , column_name ) ) , NULL , NULL , ‘, ‘ ) ||
MAX( decode( column_position , 15 , column_name ) ) FROM all_ind_columns col
WHERE col.index_name = a.index_name AND col.table_owner = a.table_owner AND col.table_name = a.table_name
) AS column_list FROM dba_indexes a
WHERE a.table_name = UPPER( TRIM( :table_name ) ) AND a.table_owner= UPPER( TRIM( :schname ) )
ORDER BY index_name
[Scrpit 4] DBA_IND_COLUMNSの活用
DBA_IND_EXPRESSIONS
DBA_IND_EXPRESSIONS はデータベースの Clusters, Tables, ViewsFUNCTION-BASEインデックス関連情報を含んでいます。
このViewの重要な列情報は[表5]のとおりです。
Column Name | Data Type | Descrption |
INDEX_OWNER | VARCHAR2(30) | インディーズ の OWNER |
INDEX_NAME | VARCHAR2(30 | INDEX の NAME |
TABLE_OWNER | VARCHAR2(30) | TABLEの OWNER 所有INDEX |
TABLE_NAME | VARCHAR2(30) | INDEX OBJECT の NAME |
COLUMN_EXPRESSION | LONG | FUNCTION-BASED INDEX COLUMN の表現式 を表します |
COLUMN_POSITION | NUMBER | INDEXは COLUMN シーケンスを設定します |
結論
この技術ホワイトペーパーでは、DBA_TABLES、DBA_TAB_COLUMNS、DBA_INDEXES、
DBA_IND_COLUMNSの簡単な活用事例と各構成列について調べています。
Oracleはパフォーマンス問題に活用できる様々なDicationary Viewを提供してきています。
それぞれのViewが持っている情報を熟知して活用すれば、SQL性能改善の判断資料として活用できると思います。