2015-10-08 2 views
-1

Я хотел бы получить полный список из id из нескольких таблиц, и они могут быть полностью перекрыты или взаимно исключены. Мне интересно, что будет иметь лучшую производительность, и это правильный способ для PostgreSQL, и почему это так?PostgreSQL: выберите отдельный id union vs. select id full join

Скажем, у меня есть 4 таблицы и таблицы оптимизированы с индексами:

[SELECT DISTINCT ... UNION]

SELECT DISTINCT id from table1 
UNION 
SELECT DISTINCT id from table2 
UNION 
SELECT DISTINCT id from table3 
UNION 
SELECT DISTINCT id from table4 
; 

[SELECT ... ПОЛНЫЙ РЕГИСТРИРУЙТЕСЬ]

SELECT DISTINCT coalesce(a.id, b.id, c.id, d.id) AS id 
FROM table1 a 
FULL JOIN table2 b on a.id=b.id 
FULL JOIN table3 c on b.id=c.id 
FULL JOIN table4 d on c.id=d.id 
; 

Сделано некоторые корректировки здесь. Благодаря предложению @ Хогана в его ответе.

Примечание

Моя вся мотивация для full join потому, что id поля может быть полностью перекрывается между таблицами. full join может облегчить некоторые сканированные таблицы.

+0

это не то же самое. – Hogan

+0

Нет необходимости в отличии от 'UNION'. 'UNION' возвращает разные значения. 'UNION ALL' возвращает все значения – lad2025

+0

@ lad2025. , , Нет необходимости, но есть случаи, когда он может создать более эффективный план выполнения (а именно, когда индекс может использоваться для 'distinct' в подзапросе). Тем не менее, эти два вопроса не являются эквивалентными, поэтому я сомневаюсь, что ОП осознает этот нюанс. –

ответ

0

Эти два варианта не являются эквивалентными. Первый делает то, что вы хотите; второй - нет. С этой точки зрения награда «производительность» идет на первое: правильные результаты превосходят более быстрые запросы.

Это фиксирует второй вариант:

SELECT id 
from table1 a FULL JOIN 
    table2 b 
    using (id) FULL JOIN 
    table3 c 
    using (id) FULL JOIN 
    table4 
    using (id); 

(. Вам нужно distinct только если одна из таблиц может иметь несколько идентификаторов)

Как с любым вопросом производительности, вы должны попробовать с вашими данными на вашей системы.

+0

это не выглядит правильным, как он узнает, из какой таблицы 'id' находится в причине select (может быть, функция postgresql, которую я не знаю)? – Hogan

+0

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

+0

@A ツ - Я всегда видел, как использование короткого выреза для объединения не как «то же самое», поскольку значения не будут совпадать с полное соединение - некоторые будут пустыми. – Hogan

0

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

  1. Создать временную таблицу с одним столбцом типа ID. Добавьте индекс в этот столбец.

  2. Для первой таблицы выберите все идентификатор и вставьте в эту таблицу.

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

  4. Выполнение фактического запроса с использованием временной таблицы.


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

SELECT DISTINCT coalesce(a.id,b.id,c.id,d.id) as id 
from table1 a 
FULL JOIN table2 b on a.id=b.id 
FULL JOIN table3 c on b.id=c.id 
FULL JOIN table4 d on c.id=d.id 

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

+0

О да, вы правы. Это то, что я имел в виду. Я отредактирую вопрос. – Boxuan

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