Просмотр производительности Oracle с помощью rownum

Я использую Oracle 10g, и у меня есть представление, которое объединяет две большие таблицы (миллионы записей). Я пытаюсь выбрать ограниченный «образец» данных для пользователя следующим образом:

select * from VIEW_NAME where ROWNUM < 5; 

Это очень медленно, и я думаю, что этого не должно быть, потому что мне просто нужно несколько строк результата, поэтому Oracle не должен вычислять полное соединение.

Требование состоит в том, что пользователь должен иметь возможность интерактивно указывать количество возвращаемых строк (неважно, какие именно строки из результата). Есть ли способ добиться этого? (с rownum или другим методом)

(Я могу изменить определение представления или способ построения окончательного SQL, но, насколько мне известно, я не могу динамически передавать информацию о желаемом количестве строк в представление)

РЕДАКТИРОВАТЬ: определение представления очень простое, примерно так:

CREATE OR REPLACE VIEW VIEW_NAME AS
(
    select
    e.id as ID,
    e.somefield as something,
    ... (some similar selects from e)
    c.field as anotherthing,
   ... (lots of other fields from c)
    from SCHEMA.TABLE1 e
    inner join SCHEMA.TABLE2 c on e.key = c.key
)

В плане объяснения упоминается полный доступ к таблицам для обеих таблиц, что неудивительно, потому что просто возврат первых нескольких строк не должен занимать много времени.

EDIT2: вот полный план

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2644394598

----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name        | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |             |     4 |  1252 |       | 43546   (1)| 00:08:43 |       |       |        |      |            |
|*  1 |  COUNT STOPKEY            |             |       |       |       |            |          |       |       |        |      |            |
|   2 |   PX COORDINATOR          |             |       |       |       |            |          |       |       |        |      |            |
|   3 |    PX SEND QC (RANDOM)    | :TQ10002    |   696K|   207M|       | 43546   (1)| 00:08:43 |       |       |  Q1,02 | P->S | QC (RAND)  |
|*  4 |     COUNT STOPKEY         |             |       |       |       |            |          |       |       |  Q1,02 | PCWC |            |
|*  5 |      HASH JOIN BUFFERED   |             |   696K|   207M|    49M| 43546   (1)| 00:08:43 |       |       |  Q1,02 | PCWP |            |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
|   6 |       BUFFER SORT         |             |       |       |       |            |          |       |       |  Q1,02 | PCWC |            |
|   7 |        PX RECEIVE         |             |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |  Q1,02 | PCWP |            |
|   8 |         PX SEND HASH      | :TQ10000    |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |        | S->P | HASH       |
|   9 |          TABLE ACCESS FULL| TABLE1      |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |        |      |            |
|  10 |       PX RECEIVE          |             |   892K|   149M|       |  5260   (1)| 00:01:04 |       |       |  Q1,02 | PCWP |            |
|  11 |        PX SEND HASH       | :TQ10001    |   892K|   149M|       |  5260   (1)| 00:01:04 |       |       |  Q1,01 | P->P | HASH       |
|  12 |         PX BLOCK ITERATOR |             |   892K|   149M|       |  5260   (1)| 00:01:04 |     1 |   140 |  Q1,01 | PCWC |            |
|  13 |          TABLE ACCESS FULL| TABLE2      |   892K|   149M|       |  5260   (1)| 00:01:04 |     1 |   140 |  Q1,01 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------

   1 - filter(ROWNUM<5)
   4 - filter(ROWNUM<5)
   5 - access("E"."KEY"="C"."KEY")

27 rows selected.

person lbalazscs    schedule 20.09.2012    source источник
comment
Что именно делает вид? Можете ли вы опубликовать источник представления? Каков план запроса для этого оператора? Что для вас значит очень медленно? Вы утверждаете, что на получение результатов уходит часы? Минуты? 5 секунд, когда вы думаете, что это должен быть ответ в секунду?   -  person Justin Cave    schedule 20.09.2012
comment
Очень медленно - 15 секунд в тестовой базе данных, но в производственной базе данных (у меня нет доступа к ней) данных в 3 раза больше. Я скоро добавлю больше информации к вопросу.   -  person lbalazscs    schedule 20.09.2012
comment
Можете ли вы опубликовать фактический план запроса? Это хеш-соединение? Присоединение к вложенному циклу? Когда вы говорите похожие выборки из e, вы имеете в виду встроенные запросы? Или просто ссылки на столбцы в e?   -  person Justin Cave    schedule 20.09.2012
comment
Он выполняет хеш-соединение и просто ссылается на столбцы в e, нет скрытых подзапросов или других уловок ... Я пытаюсь опубликовать весь план.   -  person lbalazscs    schedule 20.09.2012
comment
iirc - rownum всегда вычисляет для полного набора результатов перед применением критерия rownum к возвращаемому набору результатов. Другими словами, ограничивая ROWNUM, вы не увидите никакого прироста производительности.   -  person OraNob    schedule 21.09.2012
comment
OraNob, попробуйте с подсказкой FIRST_ROWS, вы увидите, что рассчитывается не полный набор результатов :)   -  person lbalazscs    schedule 21.09.2012


Ответы (4)


Я посмотрю, что делает подсказка /*+ NOPARALLEL */ в соответствии с ответом GuiGi. Еще одна вещь, которую можно попробовать, - это взглянуть на план, созданный для этого:

select /*+ FIRST_ROWS(10)*/ * from VIEW_NAME where ROWNUM < 5;
person Jeffrey Kemp    schedule 21.09.2012
comment
FIRST_ROWS значительно улучшает производительность (до 0,05 секунды), большое спасибо! - person lbalazscs; 21.09.2012
comment
Подсказка первой строки подразумевается из предикатов rownum (в более поздних версиях) - person Tegiri Nenashi; 24.09.2012

Вы можете попробовать добавить в запрос подсказку NOPARALLEL.

select /*+ NOPARALLEL */ * from VIEW_NAME where ROWNUM < 5; 

Это ситуация, когда выбрано параллельное выполнение, но это может отрицательно сказаться на производительности, поскольку потребует больше ресурсов ЦП и операций ввода-вывода.

person GuiGi    schedule 20.09.2012

У вас есть индекс соединения (индексированные вложенные циклы должны быть путем доступа, выбранным оптимизатором)? Попробуйте отключить hash_join (вместе с sort_merge_join), чтобы увидеть, какова стоимость альтернативной плоскости, если вы видите обычные вложенные циклы, то оптимизатор по какой-то причине проигнорировал индекс.

При настройке запросов с представлениями, встроенными в определение представления, попробуйте указать нужный путь доступа. Когда вы находите волшебные подсказки (например, количество элементов), иногда их можно переместить во внешний блок запроса (это особенно верно для более поздних версий оракула).

person Tegiri Nenashi    schedule 20.09.2012

Вы также можете попробовать:

select * FROM 
(SELECT rownum ROW_NUMBER, YOUR_VIEW.* FROM  YOUR_VIEW) 
WHERE ROW_NUMBER> 2
person Israel Margulies    schedule 11.03.2013