Oracle: могу ли я избежать большого количества СОЕДИНЕНИЙ? - PullRequest
2 голосов
/ 23 апреля 2020

У меня есть следующие таблицы в Oracle 12 c:

  • objects (около 600 K строк)
  • attributes (около 10 M строк)

Мне нужно перенести атрибуты объектов в другую таблицу. Идея показана на рисунке ниже.

Для этого сейчас я использую множество «JOIN», таких как:

SELECT
    o.id,
    o.name,
    a1.value as attr_1,
    a2.value as attr_2,
    a3.value as attr_3,
    a4.value as attr_4,
    a5.value as attr_5
FROM objects o
LEFT JOIN attributes a1 ON a1.obj_id = o.id AND a1.attr_id = 1
LEFT JOIN attributes a2 ON a2.obj_id = o.id AND a2.attr_id = 2
LEFT JOIN attributes a3 ON a3.obj_id = o.id AND a3.attr_id = 3
LEFT JOIN attributes a4 ON a4.obj_id = o.id AND a4.attr_id = 4
LEFT JOIN attributes a5 ON a5.obj_id = o.id AND a5.attr_id = 5

У меня есть несколько запросов с количеством атрибутов до 20, поэтому я имею ПРИСОЕДИНЯЙТЕСЬ к «10 M строк» ​​- 20 раз.

Это работает, но это занимает много времени.

У вас есть какие-нибудь хорошие идеи, как организовать это лучше?

enter image description here

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Одна возможность, как упомянуто в комментариях, состоит в том, чтобы использовать опцию PIVOT в SELECT. Мне не ясно, что вас беспокоит по этому поводу - вы просто говорите, что хотите сами определить фактические имена столбцов? Вы можете легко создать псевдоним столбцов после операции PIVOT.

До существования PIVOT использовался стандартный метод, который я использовал и видел, как другие использовали для достижения sh, это было так:

SELECT obj_id,
       MAX(CASE WHEN attr_id = 1 THEN value ELSE NULL) AS attr_1,
       MAX(CASE WHEN attr_id = 2 THEN value ELSE NULL) aS attr_2,
       ... etc. ...
FROM attributes
GROUP BY obj_id

Для полный запрос, вы можете поместить этот подзапрос в CTE и присоединить его к objects.

. Обратите внимание, это не обязательно означает, что Oracle выполнит весь подзапрос перед выполнением объединения. В вашем случае, возможно, так как я предполагаю, что каждая строка в objects имеет соответствующие строки в attributes. Но если в запросе был установлен фильтр obj_id, он может сначала выполнить фильтрацию, а затем выполнить группировку. В любом случае, я бы определенно ожидал, что это будет более эффективно, чем многократное присоединение.

0 голосов
/ 23 апреля 2020

Вы можете использовать level и connect by для генерации SQL, как показано ниже. Но если вы дадите точный скелет SQL, мы можем использовать user_tab_Cols для генерации SQL.

   SELECT 'select o.id,o.name, 'sql_text
    FROM   dual
    UNION ALL
    SELECT 'a.'
           ||LEVEL
           ||'.values as attr_'
           ||LEVEL
           ||',' sql_text
    FROM   dual
    CONNECT BY LEVEL <= 5
    UNION ALL
    SELECT 'FROM objects o '
    FROM   dual
    UNION ALL
    SELECT 'LEFT JOIN attributes a'
           ||LEVEL
           ||' ON a'
           ||LEVEL
           ||'.obj_id = o.id AND a'
           ||LEVEL
           ||'.attr_id = '
           ||LEVEL
    FROM   dual
    CONNECT BY LEVEL <= 5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...