Подвыбор (вместо числовой константы) ухудшает оптимизацию

Мой вопрос похож на Отбирать или не отбирать? но я хотел бы продолжать использовать два существующих представления (следовательно, я не хочу перемещать подвыбор непосредственно в логику представления).

Медленно (1,5 секунды)

SELECT h.n
FROM   v_headers h 
WHERE  h.n >= (select 3000 from dual);

Запрос выполняется быстро при непосредственном использовании значения из подвыбора:

SELECT h.n
FROM   v_headers h 
WHERE  h.n >= 3000;

Немного подробнее: n не уникально, имеет значения от 0 до 4000; для каждого n существует около 50 строк. 11 значений из разных строк поворачиваются в столбцы вдоль n.

Есть ли решение без извлечения выборок за представлениями (или изменения таблиц)? Может оптимизатор намекает?

Первый - медленный, второй - быстрый:введите описание изображения здесь

Л.Э.: Я упростил запросы.


Упрощенные запросы работают быстро благодаря @nop77svk. Более сложный запрос не (пока):

Быстро:

with xyz$ as (select 3986 as n from dual)
SELECT h.hw_number
  FROM xyz$ X
  JOIN v_headers h
    ON h.hw_number >= x.n

Медленно (и все еще несколько упрощено):

with xyz$ as ((SELECT nvl(MAX(n), 0) AS n
           FROM (SELECT h.hw_number AS n,
                        Rank() OVER(ORDER BY h.hw_number DESC) rnk
                   FROM x_data h
                  GROUP BY h.hw_number)
          WHERE rnk = 50))
SELECT h.hw_number
  FROM xyz$ X
  JOIN v_headers h
    ON h.hw_number >= x.n;

новый запрос


Немного подробнее о представлении v_headers:

WITH s AS
(
       SELECT a.n,
              b.col_name,
              a.value,
              b.col_id
       FROM   qa_data a
       JOIN   column_def b
       ON     b.col_id = a.col_id
       WHERE  b.master_dynamic_data = 'M' )
SELECT   "n","c1","c2","c3","c4","c4","c5","c6","c7","c8","c9","c10"
FROM     s PIVOT( Max(value) 
                keep(dense_rank first ORDER BY col_id) FOR col_name IN (
                     'c1' c1,
                     'c2' c2,
                     'c3' c3,
                     'c4' c4,
                     'c5' c5,
                     'c6' c6,
                     'c7' c7,
                     'c8' c8,
                     'c9' c9,
                     'c10' c10,
                     'c11' c11) )

column_def

  • 72 ряда
  • 57 строк с master_dynamic_data = 'M'
  • column_def.col_id: уникальный 1..100 (с пробелами)
  • column_def.col_name: c1, c2, c3,... (фактически 20 символов вместо 'cx')

qa_data:

  • 450 тыс. Строк
  • среднее количество строк для каждого qa_data.n составляет 112 строк. (n от 1 до 4000)
  • средняя длина qa_data.value составляет 18 символов

1 ответ

В упрощенном варианте...

SELECT --+ leading(X) use_hash(H)
    H.n
FROM (select 3000 as n from dual) X
    JOIN v_headers H
        ON H.n >= X.n
;

... >= 3000 Предикат правильно разрешен как предикат доступа, что приводит к срабатыванию индексов хранилища Exadata.

Однако в полной версии нужно принудительно распространять предикат на внутреннее представление, чего, похоже, не происходит. Быстрая проверка настройки теста показывает, что распространение такого предиката (для вычисленного значения, а не константного значения) в представление объединения выполняется в порядке, а распространение предиката в поворотное представление соединения - нет.

Тот же сценарий верен при использовании (детерминированной) функции, которая предварительно вычисляет значение n вместо использования встроенного представления - предикат не переносится в представление с поворотным соединением (пробовал в 12.1.0.2).

Было бы интересно увидеть файл трассировки события 10053, чтобы понять, что происходит. (Домашнее задание для читателя.;-))

Другие вопросы по тегам