Использовать подсказки для просмотров? - PullRequest
11 голосов
/ 19 ноября 2010

У меня есть представление, и я хочу запросить свое представление таким образом, чтобы подсказать некоторый индекс из базовой таблицы, могу ли я это сделать?

Я имею в виду:

--view
create or replace view temp_view
as select col1,col2,col3
from table1,table2....

У меня есть index on table1.col1 , называемый " index1 ".

У меня есть запрос :

--query
select * 
from temp_view 
where col1=12;

И когда я вижу план объяснения этого запроса, он показывает, что в запросе не используется «index1», и я хочу указать его ..

Итак, я хочу, чтобы это было, например:

--query with hint
select /*+ index(temp_view  index1)*/* 
from temp_view 
where col1=12;

Могу ли я указать подсказки для просмотров? (Если я не хочу указывать это при создании этого представления)

Ответы [ 2 ]

14 голосов
/ 19 ноября 2010

Вы можете использовать подсказку в запросе к представлению, чтобы заставить Oracle использовать индекс для базовой таблицы. Но вам нужно знать псевдоним базовой таблицы (если есть) в базовом представлении. Общий синтаксис будет /*+ index(<<alias of view from query>> <<alias of table from view>> <<index name>>) */

Пример

1) Создайте таблицу с 10000 одинаковыми строками и создайте индекс для таблицы. Индекс не будет выборочным, поэтому Oracle не захочет его использовать

SQL> ed
Wrote file afiedt.buf

  1  create table foo
  2  as
  3  select 1 col1
  4    from dual
  5* connect by level <= 10000
SQL> /

Table created.

SQL> create index idx_foo on foo(col1);

Index created.

2) Убедитесь, что индекс не используется нормально, но Oracle будет использовать его с подсказкой

SQL> set autotrace traceonly;
SQL> select * from foo where col1 = 1;

10000 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1245013993

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 |   126K|     7   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| FOO  | 10000 |   126K|     7   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COL1"=1)

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


Statistics
----------------------------------------------------------
          9  recursive calls
          0  db block gets
        713  consistent gets
          5  physical reads
          0  redo size
     172444  bytes sent via SQL*Net to client
       7849  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL> select /*+ index(foo idx_foo) */ *
  2    from foo
  3   where col1 = 1;

10000 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 15880034

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         | 10000 |   126K|    25   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_FOO | 10000 |   126K|    25   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("COL1"=1)

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


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
        715  consistent gets
         15  physical reads
          0  redo size
     172444  bytes sent via SQL*Net to client
       7849  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

3) Теперь создайте вид. Убедитесь, что обычные запросы к представлению не используют индекс, но вынуждают его использовать, указав псевдоним представления в запросе и псевдоним таблицы из определения представления

SQL> create view vw_foo
  2  as
  3  select col1
  4    from foo f;

View created.

SQL> select col1
  2    from vw_foo
  3   where col1 = 1;

10000 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1245013993

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 |   126K|     7   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| FOO  | 10000 |   126K|     7   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COL1"=1)

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


Statistics
----------------------------------------------------------
         16  recursive calls
          0  db block gets
        715  consistent gets
          0  physical reads
          0  redo size
     172444  bytes sent via SQL*Net to client
       7849  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL> select /*+ index(vf f idx_foo) */ col1
  2    from vw_foo vf
  3   where col1 = 1;

10000 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 15880034

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         | 10000 |   126K|    25   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_FOO | 10000 |   126K|    25   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("COL1"=1)

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


Statistics
----------------------------------------------------------
         14  recursive calls
          0  db block gets
        717  consistent gets
          0  physical reads
          0  redo size
     172444  bytes sent via SQL*Net to client
       7849  bytes received via SQL*Net from client
        668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

SQL>

Однако все эти подсказки, как правило, являются последним средством при попытке настроить запрос - обычно гораздо предпочтительнее выяснить, какой информации не хватает оптимизатору, и предоставить соответствующую статистику, чтобы он мог сделать правильный выбор в отношении свой. Это гораздо более стабильное решение в будущем. Вдвойне, когда вы ограничиваетесь указанием подсказок, включающих несколько уровней псевдонимов - слишком легко для кого-то, касающегося определения представления, сломать ваш запрос, например, изменив псевдоним имени таблицы.

1 голос
/ 15 мая 2018

Я попробовал синтаксис Джастина Кейва (ответ рядом)

select /*+ index(vf f idx_foo) */ col1
from vw_foo vf
where col1 = 1;

, но у меня это не работает. Следующая сработала

select /*+ index(vf.f idx_foo) */ col1
from vw_foo vf
where col1 = 1;

Я пробовал Oracle Database 11g Enterprise Edition, выпуск 11.2.0.1.0 - 64-разрядная версия

...