天天看点

【Oracle】如何查询视图时使用索引

通常我们使用hint来固定查询计划选择走表的索引 固定表的连接等等,但是如果第一层查询的是视图呢?

yang@rac1>CREATE TABLE TA (ID NUMBER, NAME VARCHAR2(30), TYPE VARCHAR2(30));

Table created.

yang@rac1>CREATE TABLE TB (ID NUMBER, NAME VARCHAR2(30), TYPE VARCHAR2(30));

yang@rac1>create index idx_id_ta on ta(id);

Index created.

yang@rac1>create index idx_id_tb on tb(id);

yang@rac1>CREATE VIEW V_Tab AS

  2   SELECT * FROM TA

  3  UNION ALL

  4    SELECT * FROM TB;

View created.

普通的查询视图,并没有走索引。

yang@rac1> SELECT  * 

  2     FROM V_TAB

  3     WHERE ID

9996 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 4036260501

-----------------------------------------------------------------------------

| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT    |       |     1 |    47 |     2   (0)| 00:00:01 |

|   1 |  VIEW               | V_TAB |     1 |    47 |     2   (0)| 00:00:01 |

|   2 |   UNION-ALL         |       |       |       |            |          |

|*  3 |    TABLE ACCESS FULL| TA    |  4998 |   229K|     9   (0)| 00:00:01 |

|*  4 |    TABLE ACCESS FULL| TB    |  4998 |   229K|     9   (0)| 00:00:01 |

Predicate Information (identified by operation id):

---------------------------------------------------

   3 - filter("ID"

   4 - filter("ID"

Note

-----

   - dynamic sampling used for this statement (level=2)

====使用常规使用hint的方式<b>(表名 索引名称)</b>

yang@rac1&gt; SELECT /*+ index(tb  idx_id_tb) index(ta idx_id_ta) */* 

并不凑效!依然走全表扫描!

==使用 视图前缀修饰表名的方式<b>(VIVE.TABNAME  INDEX_NAME) </b>

yang@rac1&gt; SELECT /*+ index(v_tab.tb  idx_id_tb) index(v_tab.ta idx_id_ta) */* 

Plan hash value: 531820221

-------------------------------------------------------------------------------------------

| Id  | Operation                     | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT              |           |     1 |    47 |     2   (0)| 00:00:01 |

|   1 |  VIEW                         | V_TAB     |     1 |    47 |     2   (0)| 00:00:01 |

|   2 |   UNION-ALL                   |           |       |       |            |          |

|   3 |    TABLE ACCESS BY INDEX ROWID| TA        |  4998 |   229K|    18   (0)| 00:00:01 |

|*  4 |     INDEX RANGE SCAN          | IDX_ID_TA |  4998 |       |    18   (0)| 00:00:01 |

|   5 |    TABLE ACCESS BY INDEX ROWID| TB        |  4998 |   229K|  5016   (1)| 00:01:01 |

|*  6 |     INDEX RANGE SCAN          | IDX_ID_TB |  4998 |       |    17   (0)| 00:00:01 |

   4 - access("ID"

   6 - access("ID"

yang@rac1&gt;

对于创建视图的时候包含表的别名的情况:

yang@rac1&gt;CREATE VIEW V_Tab02 AS

  2   SELECT * FROM TA t1

  4    SELECT * FROM TB t2 ;

yang@rac1&gt; SELECT /*+ index(tb  idx_id_tb) index(ta idx_id) */* 

  2     FROM V_TAB02

Plan hash value: 3023640653

-------------------------------------------------------------------------------

| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT    |         |     1 |    47 |     2   (0)| 00:00:01 |

|   1 |  VIEW               | V_TAB02 |     1 |    47 |     2   (0)| 00:00:01 |

|   2 |   UNION-ALL         |         |       |       |            |          |

|*  3 |    TABLE ACCESS FULL| TA      |  4998 |   229K|     9   (0)| 00:00:01 |

|*  4 |    TABLE ACCESS FULL| TB      |  4998 |   229K|     9   (0)| 00:00:01 |

yang@rac1&gt; SELECT /*+ index(v_tab02.tb  idx_id_tb) index(v_tab02.ta idx_id) */* 

==此时必须使用创建视图的表的相对应的别名<b>(VIVE.TAB_ALIAS_NAME  INDEX_NAME) </b>

yang@rac1&gt; SELECT /*+ index(v_tab02.t2  idx_id_tb) index(v_tab02.t1 idx_id) */* 

Plan hash value: 3173198873

|   1 |  VIEW                         | V_TAB02   |     1 |    47 |     2   (0)| 00:00:01 |

|*  4 |     INDEX RANGE SCAN          | IDX_ID    |  4998 |       |    18   (0)| 00:00:01 |