ГДЕ и ПРИСОЕДИНЯЙТЕСЬ порядок работы - PullRequest
12 голосов
/ 18 октября 2010

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

Я использую Teradata.И у меня есть 2 таблицы: table1, table2.

table1 имеет только столбец id.
table2 имеет следующие столбцы: id, val

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

Заявление 1.

SELECT table1.id, table2.val
FROM table1
INNER  JOIN table2
ON table1.id = table2.id
WHERE table2.val<100

Заявление 2.

SELECT table1.id, table3.val
FROM table1
INNER JOIN (
    SELECT *
    FROM table2
    WHERE val<100
)  table3
ON table1.id=table3.id

У меня такие вопросы: будет ли оптимизатор запросов достаточно умен, чтобы
- сначала выполнить предложение WHERE, а затем СОЕДИНИТЬСЯ позже в операторе 1
- знать, что таблица 3 на самом деле не нужна в заявлении 2

IЯ довольно плохо знаком с SQL, поэтому, пожалуйста, научите меня, если я что-то неправильно понимаю.

Ответы [ 4 ]

5 голосов
/ 18 октября 2010

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

вы не говорите, какая база данных, но вот несколько способов:
MySql EXPLAIN
SQL Server SET SHOWPLAN_ALL (Transact-SQL)
Oracle EXPLAIN PLAN

что объяснить в терадате?
Teradata Получайте и сравнивайте планы быстрее с помощью Visual Explain и ведения журнала планов XML

4 голосов
/ 21 октября 2010

В зависимости от наличия статистики и индексов для рассматриваемых таблиц механизм перезаписи запросов в оптимизаторе может или не может сканировать Table2 для записей, где val < 100 перед сканированием Table1.

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

SELECT table1.id, table3.val
FROM table1
INNER JOIN (
    SELECT table2.id, tabl2.val
    FROM table2
    WHERE val<100
    GROUP BY 1,2
)  table3
ON table1.id=table3.id

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

Механизм переписывания запросов постоянно обновляется от одного выпуска к другому, и подробности о том, как он работает, можно найти в Руководство по обработке транзакций SQL для Teradata 13.0.

0 голосов
/ 19 октября 2010

Q1. сначала выполнить предложение WHERE, а затем ПРИСОЕДИНИТЬСЯ в операторе 1

Дело в том, что если вы переключаете порядок внутреннего соединения, то есть table2 INNER JOIN table1, то я предполагаю, что предложение WHERE может быть обработано перед операцией JOIN, на этапе подготовки. Однако, я полагаю, даже если вы не измените исходный запрос, оптимизатор сможет изменить их порядок, если он считает, что операция объединения будет слишком дорогой при извлечении всей строки, поэтому сначала он будет применяться ГДЕ. Просто мое предположение.

Q2. знать, что таблица 3 на самом деле не нужна в заявлении 2

Teradata будет интерпретировать ваш второй запрос таким образом, что потребуется производная таблица, поэтому она продолжит обработку таблицы 3. Это связано с операцией.

0 голосов
/ 18 октября 2010

Если я что-то упустил, зачем вам даже Таблица1 ??

Просто запрос Table2

Select id, val  
From table2  
WHERE val<100 

или вы используете строки в таблице1 в качестве фильтра? то есть, table1 только копирует подмножество идентификаторов в Table2 ??

Если так, то это тоже будет работать ...

 Select id, val  
 From table2  
 Where val<100 
   And id In (Select id 
              From table1)

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

...