Подтвердить что ты не робот

Объединение Oracle - Сравнение между традиционным синтаксисом VS ANSI Syntax

Задержка, я вижу слишком много вундеркиндов, комментирующих вопросы Oracle, говорящие, что "Не используйте (+) оператор, скорее используйте синтаксис JOIN".

Я вижу, что оба работают хорошо. Но какова реальная разница в использовании их и что заставляет вас чувствовать их использование? Я бы приветствовал ответы, больше из опыта.

 1. Is there anything to do with limitations in application, performance, 
    etc. while using them?

 2. What would you suggest for me?

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

Примечание. Я планирую перенести более 200 пакетов и процедур, если вместо (+)

следует использовать ключевое слово,
  3. Also is there any freeware tools to do the rewrite?

Проводка образцов

+----------------------------------+------------------------------------------------+
|-INNER JOIN - CONVENTIONAL        |-INNER JOIN - ANSI SYNTAX                       |
|----------------------------------|------------------------------------------------|
|SELECT                            |SELECT                                          |
|      EMP.DEPTNO                  |       ENAME,                                   |
|FROM                              |       DNAME,                                   |
|      EMP,                        |       EMP.DEPTNO,                              |
|      DEPT                        |       DEPT.DEPTNO                              |
|WHERE                             | FROM                                           |
|      EMP.DEPTNO = DEPT.DEPTNO;   |       SCOTT.EMP INNER JOIN SCOTT.DEPT          |
|                                  |       ON EMP.DEPTNO = DEPT.DEPTNO;             |
|----------------------------------|------------------------------------------------|
|-LEFT OUTER JOIN - CONVENTIONAL   |-LEFT OUTER JOIN - ANSI SYNTAX                  |
|----------------------------------|------------------------------------------------|
|SELECT                            | SELECT                                         |
|      EMP.DEPTNO                  |       ENAME,                                   |
|FROM                              |       DNAME,                                   |
|      EMP,                        |       EMP.DEPTNO,                              |
|      DEPT                        |       DEPT.DEPTNO                              |
|WHERE                             | FROM                                           |
|      EMP.DEPTNO = DEPT.DEPTNO(+);|       SCOTT.EMP LEFT OUTER JOIN SCOTT.DEPT     |
|                                  |       ON EMP.DEPTNO = DEPT.DEPTNO;             |
|----------------------------------|------------------------------------------------|
|-RIGHT OUTER JOIN - CONVENTIONAL  |-RIGHT OUTER JOIN - ANSI SYNTAX                 |
|----------------------------------|------------------------------------------------|
|SELECT                            | SELECT                                         |
|      EMP.DEPTNO                  |       ENAME,                                   |
|FROM                              |       DNAME,                                   |
|      EMP,                        |       EMP.DEPTNO,                              |
|      DEPT                        |       DEPT.DEPTNO                              |
|WHERE                             | FROM                                           |
|      EMP.DEPTNO(+) = DEPT.DEPTNO;|       SCOTT.EMP RIGHT OUTER JOIN SCOTT.DEPT    |
|                                  |       ON EMP.DEPTNO = DEPT.DEPTNO;             |
|----------------------------------|------------------------------------------------|
|-FULL OUTER JOIN - CONVENTIONAL   |-FULL OUTER JOIN - ANSI SYNTAX                  |
|----------------------------------|------------------------------------------------|
|                                  |                                                |
|SELECT                            | SELECT                                         |
|      *                           |       *                                        |
|FROM                              | FROM                                           |
|      EMP,                        |       SCOTT.EMP FULL OUTER JOIN SCOTT.DEPT     |
|      DEPT                        |       ON EMP.DEPTNO = DEPT.DEPTNO;             |
|WHERE                             |                                                |
|      EMP.DEPTNO = DEPT.DEPTNO(+) |                                                |
|UNION ALL                         |                                                |
|SELECT                            |                                                |
|      *                           |                                                |
|FROM                              |                                                |
|      EMP,                        |                                                |
|      DEPT                        |                                                |
|WHERE                             |                                                |
|      EMP.DEPTNO(+) = DEPT.DEPTNO |                                                |
|      AND EMP.DEPTNO IS NULL;     |                                                |
|__________________________________|________________________________________________|

PS: прочитайте сводку ответов для всех сгруппированных обновлений.

4b9b3361

Ответ 1

Группировка ответов вместе

  • Используйте явные JOIN, а не имплицитные (независимо от того, являются ли они внешними объединениями или нет) заключается в том, что намного проще создать декартовский продукт с неявными объединениями. С явным JOINs вы не можете "случайно" создать его. Чем больше таблиц задействовано, тем выше риск того, что вы пропустите одно условие соединения.
  • В принципе (+) сильно ограничен по сравнению с ANSI-соединениями. Кроме того, он доступен только в Oracle, тогда как синтаксис соединения ANSI поддерживается всеми основными СУБД
  • SQL не будет работать лучше после перехода на синтаксис ANSI - это просто другой синтаксис.
  • Oracle настоятельно рекомендует использовать более гибкий синтаксис соединения предложения FROM, показанный в предыдущем примере. Раньше были некоторые ошибки с синтаксисом ANSI, но если вы идете с последними 11.2 или 12.1, которые должны быть исправлены уже.
  • Использование операторов JOIN гарантирует, что ваш код SQL соответствует требованиям ANSI и, таким образом, позволит более легко переносить внешнее приложение для других платформ баз данных.
  • Условия соединения имеют очень низкую избирательность по каждой таблице и высокую селективность по кортежам в теоретическом кросс-продукте. Условия в заявлении where обычно имеют гораздо более высокую избирательность.
  • Oracle внутренне преобразует синтаксис ANSI в синтаксис (+), это можно увидеть в разделе "Информация о предикате" плана выполнения.

Возможный Pitfall при использовании синтаксиса ANSI на двигателе 12c

Включая возможность ошибки в JOIN в 12c. См. здесь

ПОСЛЕДУЮЩИЙ:

Quest SQL optimizer tool перезаписывает синтаксис SQL в ANSI.

Ответ 2

Если ваши 200+ пакетов работают по назначению с помощью "старомодного" синтаксиса, пусть это так. SQL не будет работать лучше после перехода на синтаксис ANSI - это просто другой синтаксис.

Все, что сказано, синтаксис ANSI чище - вы не собираетесь нормализовать соединение, если вы забудете (+) в некотором многоколоночном внешнем соединении.
В прошлом были некоторые ошибки с синтаксисом ANSI, но если вы идете с последними 11.2 или 12.1, которые должны быть исправлены уже.
Конечно, вы знаете свою среду и приоритеты лучше, как сказал SchmitzIT. Синтаксис ANSI является частью стандарта SQL, и это поможет при использовании другого продукта RDBMS.

Ответ 3

В 11g вы должны использовать синтаксис ANSI join. Он более гибкий (поддержка полных внешних соединений и секционированных соединений), а в документации указано:

Oracle настоятельно рекомендует использовать более гибкий синтаксис соединения предложения FROM, показанный в предыдущем примере.

Эта причина достаточно.

Ответ 4

Помимо причин, упомянутых другими, использование операторов JOIN гарантирует, что ваш SQL-код совместим с ANSI и, таким образом, позволит более легко переносить внешнее приложение для других платформ баз данных.

Ответ 5

Разделение предикатов на основе селективности

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

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

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

Подсказка для оптимизатора (человека!)

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

Неясно, использует ли оптимизатор Oracle реальное положение оператора SQL в качестве подсказки для оптимизации запроса. Я думаю, что он больше интересуется жесткими фактами в статистике таблицы (произошли некоторые изменения в том, как Oracle обрабатывает различные объединения в 11g R1, см. this post из команды оптимизатора Oracle для получения дополнительной информации).

По крайней мере, для меня, как для человека, очень полезно знать, имеет ли инструкция избирательность в одной таблице, когда я пытаюсь понять и оптимизировать запрос. Вы также должны рассмотреть это, когда хотите поместить несколько условий в предложение ON (например, ON (a.x=b.x AND a.y=b.y) и поставить одно из условий в кластере: просто проверьте, насколько выборочно условие.

Заключение

Для существующих запросов сохраните синтаксис как есть. Создавая новый запрос или рефакторинг существующего, попробуйте выполнить сортировку предикатов по селективности с использованием синтаксиса "JOIN ON": если он не очень доступен для выбора в одной таблице, поместите его в часть ON, иначе в части WHERE.

Ответ 6

Знак (+), используемый в Outer-соединениях, представляет собой синтаксис Oracle для соединений Outer

Из информации, полученной из надежных источников oracle, я мог видеть, что вы можете сохранить синтаксис внешнего соединения Oracle (+) для существующих пакетов, поскольку имеется 200+ пакетов, и поскольку внутренне Oracle все еще преобразует их из синтаксиса ANSI в синтаксис Oracle.

Пожалуйста, используйте синтаксис ANSI в будущем, где есть ограничения на использование оператора (+)

Пожалуйста, найдите ссылки для подробного объяснения на (+) знаке Внешние соединения, которые могут помочь вам решить вашу миграцию

Синтаксис Oracle Outer Join и синтаксис ANSI

Ограничения использования (+) Внешние соединения

Дополнительная информация о внешнем соединении Oracle

(+) Outer join Оператор рекомендуется в Java при использовании драйверов Oracle JDBC

Ответ 7

Я использовал оба подхода для разных проектов, и я предпочитаю синтаксис JOIN.

  • Существует четкое разделение для условий соединения в разделе ON и фильтрах условий в WHERE.
  • Легче читать и поддерживать большие запросов с большим количеством подключений.

Ответ 8

Говоря об опыте работы, использование JOIN, а не (+) проще, быстрее, лучше выглядит и лучше работать с решением, особенно когда вы работаете с несколькими базами данных (по синонимам), с большим количеством из таблиц в нем (например: 40+ таблиц) в большой базе данных (1000+ таблиц, некоторые таблицы с более чем 2 миллиардами строк), вы почувствуете большую разницу.

Ответ 9

Некоторые комментаторы заявили, что синтаксис (+) не допускает полного внешнего объединения. Он делает это, так что это не проблема: (ВЛЕВОЙ ВХОДНЫЙ СОЕДИНИТЕЛЬ) СОЮЗ ВСЕ (ПРАВИЛЬНЫЙ ВСТРОЕННЫЙ СОЕДИНЕНИЕ).

Другие сказали, что производительность является причиной того, чтобы сделать коммутатор. Это группа BS, особенно в SQL. Конечно, есть несколько рекомендаций, но каждый запрос и каждая база данных имеют свои особенности, вы должны настраиваться для конкретных не для общих ситуаций.

Причины перехода с (+), помимо стандартного, являются его ограничениями в отличие от нового явного синтаксиса: http://docs.oracle.com/cd/E16655_01/server.121/e17209/queries006.htm#SQLRF52354, Начните читать здесь: "Oracle рекомендует использовать синтаксис FROM FROM OUTER JOIN, а не оператор объединения Oracle".

Ответ 10

Как практика, вы всегда должны использовать синтаксис ANSI. Лучше не переделывать пакеты и процедуры. Скорее вы можете исправить ситуацию, когда выполняете какое-либо обслуживание по этим сценариям по отдельности. Из-за синтаксиса не будет никакой разницы в планах.

Оптимизатор Quest SQL перезаписывает все возможные комбинации, чтобы найти лучший план. Поэтому вам все равно нужно искать один SQL из 100 результатов.