Конструкция USING в предложении JOIN может вводить барьеры оптимизации в определенных случаях?

35

Мне стало известно, что USINGконструкция (вместо ON) в FROMпредложении SELECTзапросов может в некоторых случаях вводить барьеры оптимизации.

Я имею в виду это ключевое слово:

ВЫБРАТЬ *
Из
ПРИСОЕДИНЯЙТЕСЬ К ИСПОЛЬЗОВАНИЮ (a_id)

Просто в более сложных случаях.

Контекст: этот комментарий к этому вопросу .

Я использую это много и никогда не замечал ничего до сих пор. Я был бы очень заинтересован в тестовом примере, демонстрирующем эффект, или любых ссылках на дополнительную информацию. Мои поиски оказались пустыми.

Идеальный ответ - тестовый пример, демонстрирующий USING (a_id)худшую производительность по сравнению с предложением альтернативного соединения ON a.a_id = b.a_id- если это действительно может произойти.

Эрвин Брандштеттер
источник
2
@kgrittn: Это то, что я обычно ожидал до сих пор: это USINGнемного быстрее - это приводит к уменьшению на один столбец в матрице результатов. Ваши выводы датируются 2005 и 2008 годами. Я предполагаю, что все проблемы уже исправлены. Тем не менее , я вижу возможное ограничение: Соединения с, USINGвозможно, должны быть применены по порядку , так как результирующий столбец соединения является совместным продуктом. Тем самым потенциально ограничивающие возможности при переупорядочении СОЕДИНЕНИЙ.
Эрвин Брандштеттер
1
Я обнаружил этот поток, который, возможно, имел какое-то отношение к тому, чтобы я не использовал его так часто, как я, потому что VIEW с условием USING для соединения может вызвать проблемы при сбросе / восстановлении: archives.postgresql.org/pgsql- bugs / 2011-06 / msg00030.php У меня все еще есть ноющее чувство, что был другой поток, связанный с проблемами производительности с ИСПОЛЬЗОВАНИЕМ, где обходной путь должен был использовать ON, но я собираюсь отказаться от его поиска, я думаю. Вероятно, безопасно использовать его за пределами представлений и просто не забудьте попробовать вместо него в качестве диагностического шага, если запрос медленный.
кгриттн
1
Похоже, «использование» делает код немного читабельным, но я предполагаю, что оба поля нуждаются в одном и том же имени. Я не думаю, что использование будет иметь лучшую производительность, чем «вкл», потому что БД в любом случае должна соответствовать, это похоже на выборку, имеющую ту же производительность, что и соединение (поправьте меня, если я ошибаюсь), Разница в том, что Join более чист и проще в обслуживании.
jcho360
2
@HLGEM: Это просто символическое имя, и только с двумя таблицами, как в моем примере, нет места для путаницы. И все же я исправил вопрос. Не хотел бы поощрять неудачное использование в idкачестве имени столбца.
Эрвин Брандштеттер
2
@ChristiaanWesterbeek: я не согласен. Ответ «Post-Gres» для подробного ответа Postgres - это (по-прежнему) рассылка. Только очень немногие разработчики Postgres активны на SO, но все разработчики и эксперты Postgres читают список рассылки
a_horse_with_no_name

Ответы:

12

Эрвин: Я бы согласился с идеей, что ИСПОЛЬЗОВАНИЕ, вызывающее жесткое упорядочение, вполне может создать множество крайних случаев, когда оптимальные планы будут исключены. Я недавно помог кому-то, у кого было что-то подобное в его запросе:

LEFT JOIN ( 
     a 
     JOIN b ON a.id = b.a_id
     JOIN c ON b.c_id = c.id
) ON a.id = something.a_id
LEFT JOIN (
     table1 t1
     JOIN table2 t2 ON t1.some_field = t2.other_field
     JOIN talbe3 t3 ON t2.yafield = t3.something_else
) ON ....
repeat a few more times

В его случае наихудшим из этих блоков соединения было соединение с вложенным циклом через примерно 200 тыс. Строк, примерно 20 тыс. Раз (делайте математические расчеты), и поскольку ключи не могли быть переданы в индексы, это было последовательное сканирование. Это означало, что общий запрос занимал около 3 часов из-за каскадных изменений плана. Распределение левого соединения позволяет нажимать клавиши и выполнять запрос за считанные секунды. Конечно, это не совсем эквивалентно, поэтому планировщик не может рассматривать их как эквивалентные, поэтому осталось выяснить этот план как хеш-соединение, а затем выполнить вложенный цикл, который был мучительно медленным.

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

Крис Траверс
источник