Почему СОЮЗ по двум числам эффективнее их суммы? - PullRequest
0 голосов
/ 23 января 2019

Мы хотим убедиться, что в местоположении имеется не более палитр maxCount (с определенным типом инвентаря). Чтобы гарантировать это, мы суммируем местоположения с палитрами на них или местоположения, к которым будут располагаться палитры. Оба утверждения работают нормально. Тем не менее, мой первоначальный проект был не очень эффективным. Мой советник придумал другой черновик, который намного быстрее, но он не мог объяснить, почему.

Медленное утверждение:

 AND maxCount > ( 
    SELECT 
        trptoloc+atloc
    FROM
        (
            SELECT
                COUNT(DISTINCT loc2.locnam) AS atloc
            FROM
                loc_t loc2,
                pal_t pal,
                inv_t inv,
                art_t art
            WHERE
                loc.group = loc2.group
                AND   pal.locnam = loc2.locnam
                AND   inv.palnam = pal.palnam
                AND   inv.artid = art.artid
                AND   AND   art.feature = value
        ),
        (
            SELECT
                COUNT(DISTINCT loc2.locnam) AS trptoloc
            FROM
                trp_t trp,
                loc_t loc2,
                inv_t inv,
                art_t art
            WHERE
                trp.locnamezl = loc2.locnam
                AND   trp.palnam = inv.palnam
                AND   loc.group = loc2.group
                AND   inv.artid = art.artid
                AND   art.feature = value;
        )
)

Более быстрое утверждение:

AND maxCount > (
 SELECT
 SUM(invpal)
 FROM
 (SELECT
    COUNT(distinct inv.palnam) AS invpal
    FROM
        inv_t inv,
        art_t art,
        pal_t pal,
        loc_T loc2
    WHERE
        inv.artid = art.artid
        AND   loc.group = loc2.group
        AND   pal.locnam = loc2.locnam
        AND   inv.palnam = pal.palnam
        AND   art.feature = value;
  UNION ALL
    SELECT COUNT(distinct inv.palnam) AS invpal
    FROM
        inv_t inv,
        art_t art,
        trp_t trp,
        loc_T loc2
    WHERE
        trp.locnamezl = loc2.locnam
        AND   trp.palnam = inv.palnam
        AND   loc.group = loc2.group
        AND   inv.artid = art.artid
        AND   art.feature = value;
)
)

Любая подсказка или ссылка, которая поможет мне понять разницу в производительности, приветствуется!

1 Ответ

0 голосов
/ 23 января 2019

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

В примере UNION ALL оптимизатор не должен делать ничего сложного - он просто запускает первую половину, затем запускает вторую половину, а затем суммирует две строки. Он не пытается хранить оба запроса в памяти одновременно, чтобы сравнивать их друг с другом.

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

AND maxCount > (
  select count(distinct inv.palnam)
  from inv_t inv
  join art_t art 
        on inv.artid = art.artid and art.feature = value
  join loc_T loc2 
        on loc.group = loc2.group
  left join pal_t pal 
        on pal.locnam = loc2.locnam
        and pal.palnam = inv.palnam 
  left join trp_t trp 
        on trp.palnam = inv.palnam
        and trp.locnamezl = loc2.locnam
  where pal.palnam is not null or trp.palnam is not null
)

Я также переписал его, чтобы использовать явные объединения ANSI, как предлагал Гордон.

...