Oracle: есть ли логическая причина не использовать параллельное выполнение с подзапросами в списке SELECT? - PullRequest
2 голосов
/ 16 марта 2012

Есть ли логическая причина для Oracle не использовать параллельное выполнение со скалярными подзапросами в списке SELECT?Почему он не должен их использовать?

Оператор SELECT можно распараллелить, только если выполнены следующие условия:

  • Запрос включает в себя параллельную спецификацию подсказки(PARALLEL или PARALLEL_INDEX) или объекты схемы, на которые есть ссылка в запросе, имеют ассоциированное с ними объявление PARALLEL.

  • Как минимум для одной из таблиц, указанных в запросе, требуется одно из следующего:

    • полное сканирование таблицы

    • сканирование диапазона индексов, охватывающее несколько разделов

  • Нет скалярных подзапросов в списке SELECT.

1 Ответ

4 голосов
/ 16 марта 2012

Каждый элемент в этом списке неправильный.

(По крайней мере, для Oracle 11gR2, а также, вероятно, 10g. Список можетбыть точным для некоторых устаревших версий Oracle.)

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

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


Пример:

SQL> --Create a table without any parallel settings
SQL> create table parallel_test(a number primary key, b number);

Table created.

SQL> --Create some test data
SQL> insert into parallel_test
  2  select level, level from dual connect by level <= 100000;

100000 rows created.

SQL> commit;

Commit complete.

SQL> --Force the session to run the query in parallel
SQL> alter session force parallel query;

Session altered.
SQL> --Generate explain plan
SQL> explain plan for
  2  select a
  3     ,(
  4             select a
  5             from parallel_test parallel_test2
  6             where parallel_test2.a = parallel_test.a
  7     )
  8  from parallel_test;

Explained.

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

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3823224058

---------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name         | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |              |   116K|  1477K|     9   (0)| 00:00:01 |        |      |            |
|*  1 |  INDEX UNIQUE SCAN      | SYS_C0028894 |     1 |    13 |     1   (0)| 00:00:01 |        |      |            |
|   2 |  PX COORDINATOR         |              |       |       |            |          |        |      |            |
|   3 |   PX SEND QC (RANDOM)   | :TQ10000     |   116K|  1477K|     9   (0)| 00:00:01 |  Q1,00 | P->S | QC (RAND)  |
|   4 |    PX BLOCK ITERATOR    |              |   116K|  1477K|     9   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   5 |     INDEX FAST FULL SCAN| SYS_C0028894 |   116K|  1477K|     9   (0)| 00:00:01 |  Q1,00 | PCWP |            |
---------------------------------------------------------------------------------------------------------------------

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

   1 - access("PARALLEL_TEST2"."A"=:B1)

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

21 rows selected.

SQL>

Без параллельных подсказок, без параллельных объектов, без полных сканирований таблицы, без сканирования диапазона индекса, охватывающего несколько разделов, и скаляраподзапрос.

Не выполнено ни одного условия , однако в запросе все еще используется параллелизм.(Я также проверил v$px_process, чтобы убедиться, что запрос действительно использует параллелизм, и это не просто сбой плана объяснения.)


Это означает ответ на ваш другой вопрос не так.

Я не совсем уверен, что происходит в этом случае, но я думаю, что это связано с оптимизацией FAST DUAL.В некоторых контекстах DUAL не используется в качестве таблицы, поэтому распараллеливать нечего.Вероятно, это «ошибка», но если вы используете DUAL, то вам все равно не нужен параллелизм.(Хотя я предполагаю, что вы использовали DUAL для демонстрационных целей, и ваш реальный запрос более сложный. Если это так, вам может потребоваться обновить запрос с более реалистичным примером.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...