2016-10-18 2 views
0

При подготовке некоторых запросов, я писал это:Присоединяется, условия и скорость в SQL

SELECT * 
FROM ta A 
JOIN tb B 
    ON A.col1 = B.col1 
JOIN tc C 
    ON B.col2 = C.col2 
WHERE B.col3 = 'whatever' 
AND C.col4 = 'whatever2' 

И я начал думать о следующем:

SELECT * 
FROM ta A 
JOIN (SELECT * FROM tb WHERE col3 = 'whatever') B 
    ON A.col1 = B.col1 
JOIN (SELECT * FROM tc WHERE col4 = 'whatever2') C 
    ON B.col2 = C.col2 

(если я не ошибаюсь , результат будет таким же). Мне интересно, будет ли это значительно быстрее? Я предполагаю, что это было бы, но мне было бы интересно узнать, почему/почему нет?

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

(В случае, если это имеет значение, двигатель Vertica, но мой вопрос не очень специфичен для Vertica)

+0

Являются ли они одинаковыми? Попробуй. Что быстрее? Попробуй. Используйте локальный тестовый сервер. У вас его нет? Установите его. –

+0

Я помню, что задавал себе тот же вопрос для «Oracle», и когда я проверил план объяснений, это было похоже. Вы можете попробовать то же самое для своего db. – Utsav

+0

Ваш вопрос * * относится к Vertica, поскольку он зависит от того, как оптимизируется запрос. Обычно способ решения такой производительности - это индексы, разбиение на разделы и выбор алгоритмов. Как правило, мы зависим от оптимизатора, чтобы принимать разумные решения. –

ответ

1

Ваш второй запрос поодаль, он должен быть:

SELECT * 
FROM ta A 
JOIN (SELECT * FROM tb WHERE tb.col3 = 'whatever') B 
    ON A.col1 = B.col1 
JOIN (SELECT * FROM tc WHERE tc.col4 = 'whatever2') C 
    ON B.col2 = C.col2 

Обратите внимание на вид рядный, где пункты должны ссылаться на таблицу в объеме, а не псевдоним для просмотра. B и C выходят за рамки встроенных представлений.

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

Вы можете разумно полагаться на оптимизатор сделать следующее:

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

Это говорит, что не должно быть никакой разницы между этими двумя заявлениями. Скорее всего, это толкает предикаты для первого, чтобы сделать его более похожим на второй. Если у вас есть статистика, оптимизатор должен быть достаточно умным, чтобы запросить их одинаково (или действительно закрыть).

Это не значит, что я не видел то, что у вас есть в вашем втором вопросе «исправить» проблемы для меня в Vertica ... но обычно это только когда я использую несколько выражений или тета-соединения и т. Д. .

Теперь, если это было внешнее соединение, то утверждения были бы разными. Первый будет применять фильтр после объединения, второй - до объединения.

Конечно, я упомянул, что вам действительно нужно просто объяснить оба метода. Просто убедитесь, что статистика собрана.

Надеюсь, это поможет.

0


Hi,
Очень хорошая попытка. Действительно оценен. Ваш первый запрос будет работать нормально, но второй запрос не будет выполнен и вызывает ошибку. Причина в том, что вы принимаете JOIN (SELECT * FROM tb WHERE B.col3 = 'whatever') B ON A.col1 = B.col1. В этом состоянии вы сопоставляете столбец с A.col1 = B.col1. Здесь вы получите A.col1 от ta стол, но вы не получите B.col1. При указании суб-запроса в соединении не следует использовать оператор '*'. Соединения не будут распознавать этот оператор в подзапросе. Вам нужно указать необходимые имена столбцов. Как пример в нижнем запросе,

SELECT * 
FROM ta A 
JOIN (SELECT col1,col2 FROM tb WHERE B.col3 = 'whatever') B 
    ON A.col1 = B.col1 
JOIN (SELECT col2 FROM tc WHERE C.col4 = 'whatever2') C 
    ON B.col2 = C.col2 

Это выполнит и даст вам результат. Два столбца берутся в первом запросе соединения col1, col2, так как вы используете условие B.col2 из таблицы B во втором состоянии соединения. В предложении select вы можете предоставить оператор '*', который предоставляет вам все столбцы из всех трех таблиц. Но вы не должны использовать оператор в подзапросе соединения, поскольку соединения закодированы таким образом.
Оба запроса не имеют большой разницы, но ваша первая логика будет выполняться быстрее по сравнению со второй. Во второй логике используются два подзапроса, которые делают несколько поисков в базе данных и обеспечивают результат медленнее, чем первая логика.

Надеюсь, вы получили то, о чем просите, если все еще есть какие-либо проблемы, вы можете задать любые вопросы

Смежные вопросы