Запрос к представлению выполняется медленнее, чем прямой запрос — в Oracle

Я попытался создать представление с параметрами для динамического получения данных.
(Я не могу использовать условие WHERE, так как сам оператор выбора изменяется в зависимости от параметров)

Для этого я написал процедуру, которая возвращает мне необходимые данные как тип объекта оракула.

FUNCTION get_data(p_pk_id  NUMBER, p_tab_type VARCHAR2)
RETURN M_TYPE_DATA_TAB
AS
v_table_collection M_TYPE_DATA_TAB;
BEGIN

-- my sql query which will change based on the params

RETURN v_table_collection;
END;

и я запускаю запрос выбора следующим образом.

SELECT * FROM TABLE(get_data(12345, 'MYTAB'));

что дает мне данные менее чем за 1 секунду.

для того же оператора select я создал представление как

CREATE OR REPLACE VIEW my_view
AS SELECT * FROM TABLE(get_data(12345, 'MYTAB'));

если я запрашиваю представление

SELECT * FROM my_view

для получения тех же данных требуется более 6 секунд.

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


person Madhusudhan Dollu    schedule 12.12.2013    source источник
comment
Здесь очень поможет полностью воспроизводимый тестовый пример. В общем, простое добавление select * from поверх чего-либо не имеет значения. Нам нужно точно знать, что делает ваше дело особенным.   -  person Jon Heller    schedule 13.12.2013
comment
@jonearles: как сказал Гунтрам Блом, когда я запрашиваю из представления, оно выполняет полное сканирование таблицы, тогда как прямой запрос использует все индексы базовой таблицы для более быстрого получения данных.   -  person Madhusudhan Dollu    schedule 13.12.2013
comment
Это полезно, но мы все еще не добрались до корня проблемы. Я хотел бы знать, почему он использует FTS вместо индекса.   -  person Jon Heller    schedule 13.12.2013


Ответы (2)


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

Попробуйте сделать:

 SELECT/*+gather_plan_statistics*/ * FROM TABLE(get_data(12345, 'MYTAB'));

затем выполните:

 SELECT/*+gather_plan_statistics*/ * FROM my_view

Это даст вам фактический план выполнения операторов.

Кстати, вам нужно будет выбрать в представлениях V_$SQL_PLAN и V_$SQL, чтобы использовать сбор_план_статистики, как указано выше.

person Tomás    schedule 12.12.2013
comment
Также обратите внимание, что грант требуется для представлений V_$SQL..., а не для V$SQL... Это связано с тем, что представления V$SQL на самом деле являются синонимами. Однако затем вы можете выбрать один из этих синонимов. - person Tomás; 13.12.2013

Найдите в Google «объяснить план» и проверьте план выполнения для обоих утверждений. Без полной функции сложно что-либо сказать. Но я бы предположил, что оптимизатор выполняет некоторую «общую оптимизацию» в представлении, и когда вы выбираете из представления, используется эта общая оптимизация. Когда вы выбираете напрямую, без представления, оптимизатор также учитывает внутренности вашей функции.

Попробуйте объяснить план по разным утверждениям, выбирая из представления. Является ли «внутренняя часть», которая выполняет функцию, одинаковой в каждом случае?

person Guntram Blohm    schedule 12.12.2013
comment
Да, я вижу огромную разницу в плане объяснения для просмотра и прямого запроса. прямой запрос с использованием всех индексов в таблице, где в качестве представления выполняется полное сканирование таблицы. - person Madhusudhan Dollu; 13.12.2013
comment
in Внутренняя часть функции, где условия различаются в зависимости от параметров. они будут динамически добавлены, и будет выполнен окончательный запрос для получения результата - person Madhusudhan Dollu; 13.12.2013