Выполнение PostgreSQL двух объединений и предложение NOT EQUAL между ними - PullRequest
0 голосов
/ 28 марта 2020

По сути, у нас есть таблица фактов (в действительности она разделена и имеет довольно широкую структуру) - транзакционная таблица, stati c после того, как транзакция загружена и никогда не меняет идентификаторы, которые у нее есть, и там у нас есть два поля, которые являются идентификаторами одного и того же измерения (атрибуты этого измерения могут изменяться время от времени).
И нам необходимо запросить все записи из таблицы фактов, которые не имеют одинакового «имени» в одной строке таблицы измерений.
Как мы там можно добиться лучшей производительности?

Дополнительно:

  • Таблицы фактов и измерений заполняются по расписанию, поэтому, если мы сможем улучшить производительность, добавив несколько таблиц сопоставления - это можно сделать
  • Индексы, массивы, составные индексы - что угодно
  • PostgreSQL 10 (если в 11 и 12 есть что-то, что может помочь - советы приветствуются)
  • Код ниже

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

Таблица фактов

select 
    generate_series as row_id
    ,(random()*1000000)::bigint as id1
    ,(random()*1000000)::bigint as id2
into table_fact
from generate_series(1,10000000);

Таблица измерений

select 
    generate_series as row_id
    ,'Dimension #' || (random()*10000)::bigint as dim
into table_dim
from generate_series(1,1000000);

Запрос

select
     tf.row_id
    ,tf.id1
    ,tf.id2
    ,td1.dim
    ,td2.dim
from table_fact tf
left join table_dim td1 on tf.id1=td1.row_id
left join table_dim td2 on tf.id2=td2.row_id
where not (td1.dim = td2.dim);

1 Ответ

0 голосов
/ 28 марта 2020

Ваш запрос должен быть в порядке, потому что у вас должны быть индексы в соответствующих столбцах измерения. Но left join не кажется подходящим, потому что вам требуется совпадение. Итак:

select tf.row_id , tf.id1, tf.id2, td1.dim ,td2.dim
from table_fact tf join
     table_dim td1
     on tf.id1 = td1.row_id join
     table_dim td2 
     on tf.id2 = td2.row_id
where td1.dim <> td2.dim;

Поскольку вам нужны оба имени из обоих измерений, я думаю, вам нужно отсканировать table_fact.

...