Следующие запросы SQL одинаковы:
SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;
SELECT column1, column2
FROM table1 JOIN table2
ON table1.id = table2.id;
И, конечно же, приводят к одинаковым планам запросов на каждой СУБД, которую я когда-либо пробовал.
Но время от времени я читаю или слышу мнение, что одно определенно лучше другого. Естественно, эти претензии никогда не подтверждаются объяснением.
Там, где я работаю, вторая версия, похоже, пользуется популярностью у большинства других разработчиков, поэтому я также склоняюсь к этому стилю, чтобы минимизировать удивление. Но в глубине души я действительно думаю о первом (поскольку именно так я это и выучил).
Является ли одна из этих форм объективно лучше другой? Если нет, то каковы причины использования одного над другим?
sql
coding-style
SingleNegationElimination
источник
источник
Ответы:
Я считаю, что вторая форма лучше. Это может быть потому, что так я это узнал, я признаю, но у меня есть одна конкретная причина - разделение интересов. Размещение полей, которые вы используете для объединения таблиц в предложении where, может привести к трудностям в понимании запросов.
Например, возьмите следующий запрос:
Приведенный выше запрос содержит таблицы, объединяющие условия и фактические условия бизнес-логики, объединенные в одно пространство. С большим запросом это может быть очень трудно понять.
Однако теперь возьмите этот код:
В этом случае все, что связано с таблицами или их связями, изолировано от предложения from, тогда как фактическая бизнес-логика для ограничения запросов находится в предложении where. Я думаю, что это гораздо более понятно, особенно для больших запросов.
источник
Синтаксис объединения заменил старый синтаксис запятой в 1992 году. В настоящее время нет причин писать код с синтаксисом запятой. Вы ничего не получаете и у вас есть проблемы, которых у вас просто нет с явным синтаксисом.
Во-первых, когда вы получаете более сложные запросы, очень легко выполнить случайное перекрестное соединение, пропустив условие where. Это то, что может предотвратить явный синтаксис соединения, поскольку вы получите синтаксическую ошибку.
Если вы намереваетесь использовать перекрестное объединение, явный синтаксис соединения прояснит это, в то время как в неявном синтаксисе кто-то, выполняющий обслуживание, может предположить, что вы забыли добавить предложение where.
Затем возникает проблема левого и правого объединений, которые являются проблематичными по крайней мере в некоторых БД с использованием неявного синтаксиса. Они устарели в SQL Server и фактически не дают достоверных результатов даже в старых версиях. Ни один запрос, требующий внешнего объединения, не должен содержать неявный синтаксис в SQL Server.
Кроме того, я видел вопросы здесь и на других сайтах, где неправильные результаты возникали, когда люди смешивали неявные и явные объединения (например, при добавлении левого объединения), поэтому смешивать их - плохая идея.
Наконец, многие люди, которые используют неявные объединения, на самом деле не понимают объединения. Это критическое понимание, которое вам необходимо для эффективного запроса к базе данных.
источник
Ха. Я просто нашел возможный ответ на свой вопрос, просматривая документацию по PostgreSQL . Суммируя, что объясняется на этой странице, результирующий запрос остается тем же, но число планов, которые оптимизатор должен учитывать, растет экспоненциально с количеством соединений.
Приблизительно после шести таких объединений число настолько велико, что время планирования запроса может быть заметным, и примерно после десяти оптимизатор переключится с исчерпывающего поиска планов на вероятностный поиск и может не прийти к оптимальному плану. ,
Установив параметр времени выполнения, вы можете указать планировщику обрабатывать явно упомянутые внутренние и перекрестные объединения иначе, чем неявные объединения, заставляя их переходить к вершине плана и не исследуя другие варианты.
Следует отметить, что поведение по умолчанию одинаково в обоих случаях, и для получения альтернативных планов требуется знание внутренних структур dbms и особенностей рассматриваемых таблиц, чтобы получить другой результат
источник
Хорошо, вот представление теории множеств:
Когда вы используете запятую для разделения двух (или более) имен таблиц, вы имеете в виду декартово произведение. Каждая строка «левой» таблицы будет «сопоставлена» (сцеплена) со строкой правой таблицы.
Теперь, если вы что-то напишите в предложении where, это все равно что поставить условие для этой «конкатенации», сообщающее, какие строки «конкатенировать» и с какими строками.
На самом деле это «объединение» строк :) и, следовательно, ключевое слово join, которое помогает обеспечить более читаемый синтаксис и более понятно, что вы «действительно» хотите объединить некоторые общие значения. Похоже на то, что @Dustin разъяснил выше.
Теперь каждая СУБД умна, т. Е. Она не рассчитывает сначала декартово произведение, а затем отфильтровывает данные (крайне расточительно), а скорее делает это на основе структуры запроса. Единственное, о чем я могу подумать, это то, что когда вы просите его «присоединиться», это все равно, что сделать присоединение явным и, вероятно, помогает выполнить код быстрее (насколько? Вам придется профилировать его и видеть), но в Разделенный запятыми регистр требует некоторого времени, чтобы «определить» оптимальную стратегию. Я могу ошибаться, но я просто делаю обоснованное предположение о том, как можно было бы его кодировать ...
источник
Я думаю, что обычно лучше использовать операторы JOIN для этого случая.
Если в будущем возникнет ситуация, которая потребует изменения оператора с INNER JOIN на OUTER JOIN, это будет гораздо проще сделать со вторым оператором.
источник
Любая СУБД сделает их одинаковыми с точки зрения исполнения. Все сводится к тому, является ли человек более читабельным и выразительным.
Используйте JOIN, чтобы было понятно, что такое соединение и что является фактическим выбором, как в:
против
В последнем случае сразу же выясняется, какое условие соединения является критерием выбора.
источник
Я только однажды видел, как эти два результата приводят к разному набору оптимизаций, и если память обслуживает, это было в ms-sql2k по очень сложному запросу. В этом примере старая форма, использованная с * =, в 4 раза увеличила производительность. Никто, включая наших технических ребят из Microsoft, не мог объяснить почему. Ребята из MS назвали это ошибкой. Я никогда не видел это снова.
Поскольку большинство СУБД достаточно умны, чтобы не выполнять полную картезианскую функцию, главная причина, по которой я могу не использовать ее (кроме того, что она устарела), заключается в том, что большинство людей в возрасте до 30-35 лет, с которыми я работал, никогда не видели старые формы раньше и теряются ужасно, когда они сталкиваются с ним.
источник
Старый стиль устарел, вы не должны его использовать.
Не должно быть даже аргумента, по которому лучше или нет. Новый код не должен использовать старый синтаксис.
источник
Одна из причин более лаконичного синтаксиса заключается в том, что он более лаконичен, поэтому, если вам удобно, его легче читать. Я думаю, что подробный случай похож на написание арифметики на языке COBOL, например, MULTIPLY A BY B CIVING C.
источник