SQL: Oracle - декартово произведение - в каком случае - PullRequest
0 голосов
/ 25 июня 2018

Чтение «Pro Oracle SQL» Карен Мортен, стр. 9 «Предложение FROM» говорит

Соединения обрабатываются в следующем порядке

  1. Перекрестное объединение
  2. Внутреннее объединение
  3. Внешнее объединение

Так всегда ли Oracle создает декартово произведение двух таблиц, участвующих в объединении, будь то внутреннее или внешнее объединение?

Таблица A имеет значения от 1 до 10 (уникально), а таблица B имеет значения (2,4,6,8)

Внутреннее соединение:

select a.a1, b.b1 from a,b where a.a1 = b.b1;

Внешнее соединение:

select a.a1, b.b1 from a,b where a.a1 = (+) b.b1;

Формируйте результат на основе

  • Создайте декартово произведение 10 * 4 и затем отобразите записи на основе критериев (внешний или эквивалентный)
  • Не создавайте декартово произведение, просто создайте набор результатов, основанный на предикате соединения (равнозначно, только если я не уверен, можно ли это сделать для внешнего объединения, я думаю, что декартово решение для продукта подходит для внешнего объединения)

1 Ответ

0 голосов
/ 25 июня 2018

Нет, он не строит декартово произведение двух таблиц для внутреннего или внешнего соединения.

База данных использует декартово объединение, когда одна или несколько таблиц не имеют условий соединения с какими-либо другими таблицами в операторе. " Руководство по настройке базы данных SQL

Итак, в вашем примере это декартово соединение, только если предложение where пусто:

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    40 |   240 |    10   (0)| 00:00:01 |
|   1 |  MERGE JOIN CARTESIAN|      |    40 |   240 |    10   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | B    |     4 |    12 |     3   (0)| 00:00:01 |
|   3 |   BUFFER SORT        |      |    10 |    30 |     7   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | A    |    10 |    30 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

    SELECT a.a1, b.b1 FROM a,b;

Обычно используется один из трех методов соединения, которые объясняются в том же документе .

В вашем случае для внутреннего соединения используется "hash join":

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b WHERE a.a1 = b.b1;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     4 |    24 |     6   (0)| 00:00:01 |
|*  1 |  HASH JOIN         |      |     4 |    24 |     6   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| B    |     4 |    12 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| A    |    10 |    30 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

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

   1 - access("A"."A1"="B"."B1")

и "внешнее хеш-соединение" для вашего внешнего соединения:

EXPLAIN PLAN FOR
SELECT a.a1, b.b1 FROM a,b WHERE a.a1 = b.b1(+);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    10 |    60 |     6   (0)| 00:00:01 |
|*  1 |  HASH JOIN OUTER   |      |    10 |    60 |     6   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| A    |    10 |    30 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| B    |     4 |    12 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

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

   1 - access("A"."A1"="B"."B1"(+))
...