Проблема производительности Oracle при получении первой строки в подзапросе

У меня проблема с производительностью в следующем примере (пример) select, который возвращает первую строку с использованием подзапроса:

SELECT ITEM_NUMBER,
       PROJECT_NUMBER,       
       NVL((SELECT DISTINCT
                   FIRST_VALUE(L.LOCATION) OVER (ORDER BY L.SORT1, L.SORT2 DESC) LOCATION
            FROM   LOCATIONS L
            WHERE  L.ITEM_NUMBER=P.ITEM_NUMBER
                   AND L.PROJECT_NUMBER=P.PROJECT_NUMBER
           ),
          P.PROJECT_NUMBER) LOCATION
FROM   PROJECT P

DISTINCT вызывает проблему с производительностью, выполняя SORT и UNIQUE , но я не могу найти альтернативы.

Однако я бы предпочел что-то похожее на следующее, но ссылки в двух операциях select не работают:

SELECT ITEM_NUMBER,
       PROJECT_NUMBER,       
       NVL((SELECT LOCATION
            FROM   (SELECT L.LOCATION LOCATION
                           ROWNUM RN
                    FROM   LOCATIONS L
                    WHERE  L.ITEM_NUMBER=P.ITEM_NUMBER
                           AND L.PROJECT_NUMBER=P.PROJECT_NUMBER
                    ORDER BY L.SORT1, L.SORT2 DESC
                   ) R
            WHERE RN <=1
           ), P.PROJECT_NUMBER) LOCATION
FROM   PROJECT P

Дополнительно:  - Мои разрешения не позволяют мне создать функцию.  - В основном запросе я езжу на велосипеде через 10k до 100k записей.  - Sub-запрос может вернуть от 3 до 7 строк до ограничения до 1 строки.

Любое содействие в улучшении производительности приветствуется.

0
nl ja de
Используйте ROW_NUMBER вместо FIRST_VALUE
добавлено автор OMG Ponies, источник
Как вы знаете, что DISTINCT является причиной вашей проблемы с производительностью? Просто потому, что вы видите, что SORT/UNIQUE в вашем плане объяснений не означает, что ваш запрос действительно сортирует или сортирует много данных, не говоря уже о получении для него производительности. Отправьте свой план объяснений.
добавлено автор Jeffrey Kemp, источник
@JeffreyKemp, +1 вы поднимаете хорошие очки. Я знаю, что нет прямой ссылки (и не нужно дискуссий) между EXPLAIN PLAN и PERFORMANCE , но объем дополнительной работы, связанной с получением решения на моем пути, Я уверен, что пропустил простое решение. Я могу использовать только EXPLAIN , чтобы оценить работу, выполняемую системой.
добавлено автор glh, источник

2 ответы

Трудно понять без выборочных данных и мощностей, но делает ли это то, что вы хотите? Уникальный список проектов и элементов, с первым вхождением местоположения?

SELECT 
P.ITEM_NUMBER,
P.PROJECT_NUMBER,       
MIN(L.LOCATION) KEEP (DENSE_RANK FIRST ORDER BY L.SORT1, L.SORT2 DESC) LOCATION
FROM   
LOCATIONS L
INNER JOIN
PROJECT P
ON L.ITEM_NUMBER=P.ITEM_NUMBER
AND L.PROJECT_NUMBER=P.PROJECT_NUMBER
GROUP BY
P.ITEM_NUMBER,
P.PROJECT_NUMBER
3
добавлено
Вам не хватает NVL, но в остальном да; это то, на что я бы ответил; он сохраняет встроенный подзапрос (который не является always злом для тех, кто читает это), но что более важно, он должен быть намного более эффективным.
добавлено автор Ben, источник
Отлично. Эти аналитические функции являются магическими. Ну не волшебство, но часто самое близкое к решению серебряной пули.
добавлено автор Nick.McDermaid, источник
Да, вы правы, это тот результат, который мне нужен. Я думаю, что ваше решение работает хорошо, определенность намного проще, чем моя. Я отвечу на завтра с результатом.
добавлено автор glh, источник
Благодаря моему запросу прошло от 2 минут до 6 секунд!
добавлено автор glh, источник

В прошлом я сталкивался с подобной проблемой - и хотя это не окончательное решение (на самом деле это может быть просто сокращение) - оптимизатор запросов Oracle можно настроить с помощью параметра OPTIMIZER_MODE init.

Have a look at chapter 11.2.1 on http://docs.oracle.com/cd/B28359_01/server.111/b28274/optimops.htm#i38318

<Р> FIRST_ROWS      

Оптимизатор использует сочетание стоимости и эвристики, чтобы найти лучший план   для быстрой доставки первых нескольких строк. Примечание. Использование эвристики   иногда приводит оптимизатор запросов для создания плана с затратами   что значительно превышает стоимость плана без применения   эвристический. FIRST_ROWS доступен для обратной совместимости и   стабильность плана; вместо этого используйте FIRST_ROWS_n.

Конечно, есть и другие факторы, которые необходимо проанализировать, например, ваш индекс, эффективность участия, план запросов и т. Д.

2
добавлено
-1 FIRST_ROWS - подсказка оптимизатора. ОП задает вопрос о подзапросе, который должен возвращать первую строку - т. Е. только первую строку - я знаю, что это запутанно, но две вещи очень разные и имеют разные цели.
добавлено автор Jeffrey Kemp, источник
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)

Oracle RU
Oracle RU
303 участник(ов)

Русскоязычная группа по Oracle. — Архитектура СУБД — PL/SQL — Оптимизация — Администрирование — Вакансии Oracle (указать инфу по вилке ЗП и удалёнке) Приглашайте коллег :-) Запрещены: личные оскорбления, обсуждения оффтопик вопросов политики и религии