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

Является ли РАБОТА быстрее, чем ГДЕ?

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

CREATE TABLE Document (
  Id INT PRIMARY KEY,
  Name VARCHAR 255
)

CREATE TABLE DocumentStats (
  Id INT PRIMARY KEY,
  DocumentId INT, -- this is a foreign key to table Document
  NbViews INT
)

Я знаю, это не самый умный способ делать что-то, но это лучший пример, который я мог бы придумать.

Теперь я хочу получить все документы с более чем 500 видами. Два решения, которые приходят мне на ум:

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

или:

SELECT *
FROM Document
INNER JOIN DocumentStats
ON Document.Id = DocumentStats.Id
WHERE DocumentStats.NbViews > 500

Являются ли оба запроса эквивалентными, или есть один путь, который намного лучше, чем другой? Если да, то почему?

Я знаю, что мой пример не идеальный, и что для запросов может потребоваться некоторая настройка, но я надеюсь, что вы поняли суть;)!

EDIT: по запросу в ответах этот вопрос был нацелен на MSSQL, но мне было бы интересно узнать, отличается ли он от других механизмов БД (MySQL и т.д.)

4b9b3361

Ответ 1

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

Ответ 2

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

Для MS-SQL оба запроса приводят к тем же планам выполнения, но имейте в виду:

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

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

Ответ 3

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

Сервер MSSql выполняет запросы в следующем порядке (это должно дать вам представление о функциях предложений WHERE и JOIN)

Порядок запросов к серверу Microsoft Sql

из превосходной серии книг о Microsoft SQL Server, внутри Microsoft SQL Server 2005: T-SQL Querying, который можно найти здесь

(Шаг 8) SELECT (Шаг 9) DISTINCT (Шаг 11)  
(Шаг 1) FROM left_table
(Шаг 3) join_type JOIN right_table
(Шаг 2) ON join_condition
(Шаг 4) ГДЕ where_condition
(Шаг 5) ГРУППА BY group_by_list
(Шаг 6) С [CUBE | ROLLUP]
(Шаг 7) having_clause
(Шаг 10) ORDER BY order_by_list

Ответ 4

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

Ответ 5

Это "стандарт" для использования синтаксиса INNER JOIN, хотя он практически эквивалентен. Основная причина, по которой его следует использовать, заключается в ясности и мобильности, поскольку она согласуется с синтаксисом OUTER JOIN.

Ответ 6

Когда вы используете Sqlite: синтаксис where немного больше, потому что Sqlite сначала переводит синтаксис соединения в синтаксис where перед выполнением запроса.

Ответ 7

Явные объединения легче поддерживать, поскольку цель запроса намного яснее. Кроме того, они не подвержены случайным кросс-соединениям, поэтому, если у вас есть кросс-соединение в запросе, то поддерживающий знает, что он должен быть там.

Если вам когда-либо понадобится использовать внешние соединения, вы должны знать, что синтаксис * = устарел на SQL Server и скоро будет удален. Также он в настоящее время не функционирует так, как ожидалось, все время и может не давать правильных результатов и, следовательно, НИКОГДА не должен использоваться. Смешение явных внешних объединений и объединение предложений (неявное объединение) делает запрос намного сложнее для читателя и его понимания.

Ответ 8

Если вы говорите конкретно о SQL Server, вам обязательно нужно использовать синтаксис INNER JOIN. Помимо того, что (личный взгляд на предупреждение!) Легче читать и более ясно в намерении, с SQL Server 2005 нет эквивалентного синтаксиса для внешних соединений. Синтаксис * = и = * по умолчанию не поддерживается в 2005 году - вам нужно включить режим совместимости для его поддержки. В конечном итоге он будет удален, возможно, как только следующий выпуск (или, возможно, нет!)

Это означает:

  • Если вам нужно изменить запрос из внутреннего соединения на внешнее соединение, вам нужно либо переписать его (argh), либо включить режим совместимости (yuk)
  • Без режима совместимости вы не можете быть совместимы с тем, как вы реализуете разные типы объединений (внутреннее и внешнее), делая для кошмара обслуживания (и, если они объединены в одном запросе, интуитивный).

Обратите также внимание на то, что, вопреки распространенному мнению, эти два не эквивалентны. Некоторые вещи гораздо более неудобны, а некоторые просто невозможны. Кален Делани Внутри SQL Server 2000 описаны некоторые примеры; не уверен, что новые версии делают, потому что этот синтаксис соединения в любом случае устарел.

Ответ 9

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

Ответ 10

Я думаю, что это тоже не имеет значения. Чтобы убедиться, что вы можете проверить, идентичен ли план объяснения этих двух запросов. Чтобы посмотреть на план объяснения в MySQL, вы должны поставить ключевое слово "объяснять" перед оператором, например:

EXPLAIN
SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

Я уверен, что в MSSQL существует эквивалент.

Кстати: Похоже, что это соотношение 1:1, поэтому я бы просто включил атрибут nbviews непосредственно в таблицу Document, поэтому вы можете сохранить соединение.