인덱스는 주로 아래의 네 가지 유형으로 명명된다. 네 가지 유형으로 생성한 인덱스의 실행 계획을 살펴보자.
- 테이블_접미어+순번
- 접두어_테이블_순번
- 접두어+순번_테이블
- 테이블_칼럼_접미어
테스트를 위해 아래와 같이 테이블과 인덱스를 생성하자.
-- 1-1 DROP TABLE t1 PURGE; DROP TABLE t2 PURGE; DROP TABLE t3 PURGE; CREATE TABLE t1 (c1 NUMBER, c2 NUMBER, c3 NUMBER, c4 NUMBER); CREATE TABLE t2 (c1 NUMBER, c2 NUMBER, c3 NUMBER, c4 NUMBER); CREATE TABLE t3 (c1 NUMBER, c2 NUMBER, c3 NUMBER, c4 NUMBER); CREATE INDEX t1_x01 ON t1 (c1); CREATE INDEX t2_x01 ON t2 (c1); CREATE INDEX t3_x01 ON t3 (c1); CREATE INDEX ix_t1_01 ON t1 (c2); CREATE INDEX ix_t2_01 ON t2 (c2); CREATE INDEX ix_t3_01 ON t3 (c2); CREATE INDEX ix01_t1 ON t1 (c3); CREATE INDEX ix01_t2 ON t2 (c3); CREATE INDEX ix01_t3 ON t3 (c3); CREATE INDEX t1_c4_ix ON t1 (c4); CREATE INDEX t2_c4_ix ON t2 (c4); CREATE INDEX t3_c4_ix ON t3 (c4);
아래는 네 가지 패턴으로 생성한 인덱스의 실행 계획다. 각기 장단점이 있겠지만 가독성 측면에서 1번 유형(2-1)을 바람직해 보인다.
-- 2-1
SELECT /*+ ORDERED USE_NL(B) USE_NL(C) */
*
FROM t1 a, t2 b, t3 c
WHERE a.c1 > 0
AND b.c1 = a.c1
AND c.c1 = b.c1;
-------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | NESTED LOOPS | |
| 3 | NESTED LOOPS | |
| 4 | TABLE ACCESS BY INDEX ROWID| T1 |
|* 5 | INDEX RANGE SCAN | T1_X01 |
| 6 | TABLE ACCESS BY INDEX ROWID| T2 |
|* 7 | INDEX RANGE SCAN | T2_X01 |
|* 8 | INDEX RANGE SCAN | T3_X01 |
| 9 | TABLE ACCESS BY INDEX ROWID | T3 |
-------------------------------------------------
-- 2-2
SELECT /*+ ORDERED USE_NL(B) USE_NL(C) */
*
FROM t1 a, t2 b, t3 c
WHERE a.c2 > 0
AND b.c2 = a.c2
AND c.c2 = b.c2;
---------------------------------------------------
| Id | Operation | Name |
---------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | NESTED LOOPS | |
| 3 | NESTED LOOPS | |
| 4 | TABLE ACCESS BY INDEX ROWID| T1 |
|* 5 | INDEX RANGE SCAN | IX_T1_01 |
| 6 | TABLE ACCESS BY INDEX ROWID| T2 |
|* 7 | INDEX RANGE SCAN | IX_T2_01 |
|* 8 | INDEX RANGE SCAN | IX_T3_01 |
| 9 | TABLE ACCESS BY INDEX ROWID | T3 |
---------------------------------------------------
-- 2-3
SELECT /*+ ORDERED USE_NL(B) USE_NL(C) */
*
FROM t1 a, t2 b, t3 c
WHERE a.c3 > 0
AND b.c3 = a.c3
AND c.c3 = b.c3;
--------------------------------------------------
| Id | Operation | Name |
--------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | NESTED LOOPS | |
| 3 | NESTED LOOPS | |
| 4 | TABLE ACCESS BY INDEX ROWID| T1 |
|* 5 | INDEX RANGE SCAN | IX01_T1 |
| 6 | TABLE ACCESS BY INDEX ROWID| T2 |
|* 7 | INDEX RANGE SCAN | IX01_T2 |
|* 8 | INDEX RANGE SCAN | IX01_T3 |
| 9 | TABLE ACCESS BY INDEX ROWID | T3 |
--------------------------------------------------
-- 2-4
SELECT /*+ ORDERED USE_NL(B) USE_NL(C) */
*
FROM t1 a, t2 b, t3 c
WHERE a.c4 > 0
AND b.c4 = a.c4
AND c.c4 = b.c4;
---------------------------------------------------
| Id | Operation | Name |
---------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | NESTED LOOPS | |
| 3 | NESTED LOOPS | |
| 4 | TABLE ACCESS BY INDEX ROWID| T1 |
|* 5 | INDEX RANGE SCAN | T1_C4_IX |
| 6 | TABLE ACCESS BY INDEX ROWID| T2 |
|* 7 | INDEX RANGE SCAN | T2_C4_IX |
|* 8 | INDEX RANGE SCAN | T3_C4_IX |
| 9 | TABLE ACCESS BY INDEX ROWID | T3 |
---------------------------------------------------
어떤 유형이든 통일된 기준으로 관리하는 것이 가장 중요하다. 아래 쿼리로 인덱스 명 변경 스크립트를 생성할 수 있다. 순번은 칼럼 순서 기준이다.
-- 3
SELECT a.table_name
, a.index_name
, 'ALTER INDEX '
|| a.owner
|| '.'
|| a.index_name
|| ' RENAME TO '
|| SUBSTR (a.table_name, 1, 26)
|| '_'
|| a.postfix
|| CASE
WHEN a.postfix <> 'PK'
THEN LPAD (ROW_NUMBER () OVER (PARTITION BY a.table_owner, a.table_name, a.postfix
ORDER BY b.column_id_list), 2, '0')
END
|| ';' AS sql_text
FROM (SELECT a.owner
, a.index_name
, a.table_owner
, a.table_name
, a.uniqueness
, b.constraint_type
, CASE
WHEN b.constraint_type = 'P' THEN 'PK'
WHEN a.uniqueness = 'UNIQUE' THEN 'U'
ELSE 'X'
END AS postfix
FROM dba_indexes a
, dba_constraints b
WHERE a.owner = 'OE' -- !
AND a.index_type = 'NORMAL' -- !
AND b.owner(+) = a.table_owner
AND b.constraint_type(+) = 'P'
AND b.table_name(+) = a.table_name
AND b.index_owner(+) = a.owner
AND b.index_name(+) = a.index_name) a
, (SELECT a.index_owner
, a.index_name
, a.table_owner
, a.table_name
, LISTAGG (LPAD (b.column_id, 3, '0'), ',') WITHIN GROUP
(ORDER BY a.column_position) AS column_id_list
FROM dba_ind_columns a
, dba_tab_cols b
WHERE a.table_owner = 'OE' -- !
AND b.owner = a.table_owner
AND b.table_name = a.table_name
AND b.column_name = a.column_name
GROUP BY a.index_owner
, a.index_name
, a.table_owner
, a.table_name) b
WHERE b.index_owner = a.owner
AND b.index_name = a.index_name
AND b.table_owner = a.table_owner
AND b.table_name = a.table_name
ORDER BY a.table_owner
, a.table_name
, a.postfix
, column_id_list;
TABLE_NAME INDEX_NAME SQL_TEXT
-------------------- ----------------------- -----------------------------------------------------------------------
CATEGORIES_TAB SYS_C0011038 ALTER INDEX OE.SYS_C0011038 RENAME TO CATEGORIES_TAB_PK;
CATEGORIES_TAB SYS_C0011041 ALTER INDEX OE.SYS_C0011041 RENAME TO CATEGORIES_TAB_U01;
CUSTOMERS CUSTOMERS_PK ALTER INDEX OE.CUSTOMERS_PK RENAME TO CUSTOMERS_PK;
CUSTOMERS CUST_LNAME_IX ALTER INDEX OE.CUST_LNAME_IX RENAME TO CUSTOMERS_X01;
CUSTOMERS CUST_EMAIL_IX ALTER INDEX OE.CUST_EMAIL_IX RENAME TO CUSTOMERS_X02;
CUSTOMERS CUST_ACCOUNT_MANAGER_IX ALTER INDEX OE.CUST_ACCOUNT_MANAGER_IX RENAME TO CUSTOMERS_X03;
INVENTORIES INVENTORY_IX ALTER INDEX OE.INVENTORY_IX RENAME TO INVENTORIES_PK;
INVENTORIES INV_PRODUCT_IX ALTER INDEX OE.INV_PRODUCT_IX RENAME TO INVENTORIES_X01;
ORDERS ORDER_PK ALTER INDEX OE.ORDER_PK RENAME TO ORDERS_PK;
ORDERS ORD_ORDER_DATE_IX ALTER INDEX OE.ORD_ORDER_DATE_IX RENAME TO ORDERS_X01;
ORDERS ORD_CUSTOMER_IX ALTER INDEX OE.ORD_CUSTOMER_IX RENAME TO ORDERS_X02;
ORDERS ORD_SALES_REP_IX ALTER INDEX OE.ORD_SALES_REP_IX RENAME TO ORDERS_X03;
ORDER_ITEMS ORDER_ITEMS_PK ALTER INDEX OE.ORDER_ITEMS_PK RENAME TO ORDER_ITEMS_PK;
ORDER_ITEMS ORDER_ITEMS_UK ALTER INDEX OE.ORDER_ITEMS_UK RENAME TO ORDER_ITEMS_U01;
ORDER_ITEMS ITEM_ORDER_IX ALTER INDEX OE.ITEM_ORDER_IX RENAME TO ORDER_ITEMS_X01;
ORDER_ITEMS ITEM_PRODUCT_IX ALTER INDEX OE.ITEM_PRODUCT_IX RENAME TO ORDER_ITEMS_X02;
PRODUCT_DESCRIPTIONS PRD_DESC_PK ALTER INDEX OE.PRD_DESC_PK RENAME TO PRODUCT_DESCRIPTIONS_PK;
PRODUCT_DESCRIPTIONS PROD_NAME_IX ALTER INDEX OE.PROD_NAME_IX RENAME TO PRODUCT_DESCRIPTIONS_X01;
PRODUCT_INFORMATION PRODUCT_INFORMATION_PK ALTER INDEX OE.PRODUCT_INFORMATION_PK RENAME TO PRODUCT_INFORMATION_PK;
PRODUCT_INFORMATION PROD_SUPPLIER_IX ALTER INDEX OE.PROD_SUPPLIER_IX RENAME TO PRODUCT_INFORMATION_X01;
PROMOTIONS PROMO_ID_PK ALTER INDEX OE.PROMO_ID_PK RENAME TO PROMOTIONS_PK;
PURCHASEORDER SYS_C0011037 ALTER INDEX OE.SYS_C0011037 RENAME TO PURCHASEORDER_U01;
WAREHOUSES WAREHOUSES_PK ALTER INDEX OE.WAREHOUSES_PK RENAME TO WAREHOUSES_PK;
WAREHOUSES WHS_LOCATION_IX ALTER INDEX OE.WHS_LOCATION_IX RENAME TO WAREHOUSES_X01;
24 행이 선택되었습니다.
'Oracle > Administration' 카테고리의 다른 글
| Hybrid Partitioned 테이블 (0) | 2019.08.22 |
|---|---|
| Partitioned External 테이블 (0) | 2019.08.22 |
| 파티션 통계정보 복사 (0) | 2019.07.26 |
| CLOB #5 - ENABLE STORAGE IN ROW (0) | 2019.02.09 |
| Covered 인덱스와 인덱스 브랜치 블록 (0) | 2019.01.06 |

