Oracle с ограничениями пункта - PullRequest
2 голосов
/ 03 июня 2019

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

CREATE VIEW
    V_VIEW
    (
        COL1, COL2, COL3, COL4
    ) AS
SELECT
    "COL1", "COL2", "COL3", "COL4"
FROM
    TABLE1
UNION ALL
SELECT
    "COL1", "COL2", "COL3", "COL4"
FROM
    TABLE2;

SELECT
        COL1, COL2
FROM
    (   SELECT
            COL1, COL2
        FROM
            V_VIEW
        WHERE
            COL1 like 'val%'
        AND COL2 =
            (
                SELECT
                    MAX(COL3)
                FROM
                    V_VIEW
                WHERE
                    COL4 = 'Y' ) part1
UNION ALL
SELECT
        COL1, COL2
FROM
    (   SELECT
            COL1, COL2
        FROM
            V_VIEW
        WHERE
            COL1 like 'sth%'
        AND COL2 =
            (
                SELECT
                    MIN(COL3)
                FROM
                    V_VIEW
                WHERE
                    COL4 = 'N' ) part2;

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

WITH TEMP_TABLE AS (
SELECT
    COL1, COL2, COL3, COL4
FROM
    TABLE1
UNION ALL
SELECT
    COL1, COL2, COL3, COL4
FROM
    TABLE2 )
SELECT
        COL1, COL2
FROM
    (   SELECT
            COL1, COL2
        FROM
            TEMP_TABLE
        WHERE
            COL1 like 'val%'
        AND COL2 =
            (
                SELECT
                    MAX(COL3)
                FROM
                    TEMP_TABLE
                WHERE
                    COL4 = 'Y' ) part1
UNION ALL
SELECT
        COL1, COL2
FROM
    (   SELECT
            COL1, COL2
        FROM
            TEMP_TABLE
        WHERE
            COL1 like 'sth%'
        AND COL2 =
            (
                SELECT
                    MIN(COL3)
                FROM
                    TEMP_TABLE
                WHERE
                    COL4 = 'N' ) part2

На небольшом объеме данных (в таблицах Table1 и Table2 около 20 тыс. Строк) это очень хорошо повышает производительность. Однако эти таблицы в конечном итоге будут заполнены миллионами строк. Я не совсем понимаю, как обрабатывается предложение WITH, поэтому мне интересно: есть ли шанс, что запрос, использующий замыкание WITH, для большого набора данных, завершится неудачей (из-за недостатка памяти?), Где запрос без него будет работать медленно, но закончится просто отлично?

Ответы [ 3 ]

1 голос
/ 03 июня 2019

Предложение WITH является своего рода VIEW, который создается на лету, используется и код не будет сохранен в БД.Однако он использует основную память для хранения информации, связанной с курсором, которая используется для извлечения строк из запроса WITH SELECT.Вы правы;Запрос WITH для таблиц с огромными данными замедлит работу БД.

Я не знаю: а) Содержат ли TABLE1 и TABLE2 полный набор данных или эти таблицы обновляются постепенно.б) У нас есть столбцы даты в этой таблице?c) Через какой промежуток времени эти таблицы заполняются или обновляются?

На основе ответов на поставленные выше вопросы: После обсуждения со своими администраторами баз данных:

  1. Вы можете попросить администраторов баз данных извлечь данные, принадлежащиеTRUNC (SYSDATE) или TRUNC (SYSDATE) -1 из TABLE1 и TABLE2 и заполняют эти данные в одну «новую» таблицу с такими же столбцами и двумя дополнительными столбцами: a) Один столбец будет содержать первые три буквы значения COL1.b) Еще один столбец для хранения значения состояния с помощью DEFAULT 'Q'.
  2. Создайте раздел LIST для этой новой таблицы на COL1 для значений 'Val' и 'Sth' и COL4 для Y и N.
  3. Напишите анонимный блок, который подготавливает данные так, как вам нужно.Затем простой запрос к этой новой таблице должен получить данные для вас.Мы можем запланировать этот анонимный блок в расписании работ в зависимости от частоты, с которой данные будут доступны в исходных таблицах TABLE1 и TABLE2.

Эти предложения основаны на ряде предположений и количестве информации, которую выподелились.

Если на этих данных запущен какой-либо пользовательский интерфейс или отчет, требуется ведение этих данных на дому.

Итог:

  1. Подготовьтеданные в соответствии с требованиями последующего процесса (ов) заранее, а не подготовки данных на лету, когда это требуется.Это также упростит весь процесс и часть запроса.
  2. В большинстве случаев, когда мы сталкиваемся с узкими местами производительности в среде Prod или Int, мы всегда ищем краткосрочные решения.Краткосрочные решения очень необходимы для решения проблемы.Однако я бы посоветовал вам подготовиться и к долгосрочному решению.
1 голос
/ 03 июня 2019

Вы можете попробовать использовать следующее:

WITH main_res AS (SELECT col1,
                         col2,
                         MAX(CASE WHEN col4 = 'N' THEN col3) OVER () col3_n_max,
                         MAX(CASE WHEN col4 = 'Y' THEN col3) OVER () col3_y_max
                  FROM   v_view
                  WHERE  col1 LIKE 'val%'
                  OR     col1 LIKE 'sth%')
SELECT col1,
       col2
FROM   main_res
WHERE  (col1 LIKE 'val%' AND col2 = col3_y_max)
OR     (col1 LIKE 'sth%' AND col2 = col3_n_max);

При этом используется условная максимальная аналитическая функция для возврата максимального значения (в зависимости от значения col4) по всем строкам.

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

0 голосов
/ 03 июня 2019

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

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

Предложение WITH весьма удобно и выполняет ту же функцию, что и автономное представление или представление, определенное встроенным в списке таблиц., с одним ключевым исключением: Oracle обрабатывает автономные представления, представления предложения WITH и встроенные представления немного по-разному в процессе оптимизации.Oracle может решить материализовать результаты представления, определенного в предложении WITH, в то время как оно может объединить представление, если оно определено встроенным.

Дело в том, что переключение между этими тремя видами представлений в вашем запросе приведет кСтранные нюансы работы оптимизатора.

Наконец, на какой версии Oracle вы работаете?Оптимизатор - это та область, где версия действительно имеет значение.

...