2013-02-12 4 views
2

У меня есть запрос, который я хотел бы сохранить в качестве вида:Повышение производительности на взгляд Oracle

WITH subquery AS (SELECT aaa_id, ... FROM table_aaa ...) 
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING (...) 
; 

[Примечание: В реальной жизни, мой запрос является гораздо более сложным, чем это, с несколькими WITH подзапросы, многие из которых выполняют JOINS, все из которых являются JOIN ed вместе. Но я ищу общее руководство, которое я могу использовать для решения моей проблемы.]

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

WITH subquery AS (SELECT aaa_id, ... FROM table_aaa ... WHERE aaa_id = :id) 
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING (...) 
; 

Однако, это не кажется, что у меня есть возможность поставить условие WHERE в нужном месте, когда я создаю вид :

CREATE OR REPLACE VIEW vw_my_view AS 
WITH subquery AS (SELECT aaa_id, ... FROM table_aaa ...) 
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING (...) 
; 

SELECT ... FROM vw_my_view WHERE aaa_id = :id 
; 

В этом случае план выполнения по-прежнему содержит полное сканирование таблицы. Есть ли способ для меня намекнуть, что предложение WHERE действительно может быть вставлено в подзапрос WITH?

+0

Что вы имеете в виду, когда говорите, что у вас нет возможности указать условие WHERE в подзапросе внутри предложения WITH? –

+0

@Darius - Это правда, что я могу указать условие «WHERE» на мой взгляд, если я хочу ограничить свое представление определенным подмножеством данных. Это не то, чего я хочу. –

+0

@Darius - Я сказал, что если запрос к представлению, добавив условие «WHERE» к этому запросу, не поместит его в нужное место в плане выполнения. (Обратите внимание, что условие 'WHERE' внутри подзапроса' WITH' состояло в том, как я зафиксировал план выполнения за пределами представления). –

ответ

1

Я имел подобный опыт и в то время как у меня нет общего решения, я хотел бы предложить следующее:

  • запустить "SELECT * FROM V $ PARAMETER2;" и убедитесь, что _complex_view_merging включен. В одном из ранних выпусков 10g, связанных с ним, была неприятная ошибка, поэтому некоторые dbas отключили ее и, возможно, забыли вернуть ее после того, как она была исправлена.

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

  • Если у вас есть базовая таблица, основным ключом которой является то, что вы в конечном счете собираетесь фильтровать, попробуйте настроить все, чтобы основной запрос вашего вида начинался с этого, а затем соединяется с вашим сложным с предложением запросов, , даже если это соединение полностью избыточно (т. е. дать оракулу возможность сделать легкую фильтрацию на этой базовой таблице перед присоединением к сложным битам). Убедитесь, что столбцы, которые будет фильтроваться, будут выбраны непосредственно из этой базовой таблицы, а не из сложной_записи. Так что-то вроде

.

 with (complicated_query) 
    select base_table.key1, complicated_query.* 
    from base_table 
    join complicated_query on base_table.key1 = complicated_query.key1; 
  • Если у вас есть фильтры, которые используют некоррелированный подзапрос, попробуйте переключить их на коррелированном эквивалентном (и наоборот).

  • Поиграйте с порядком ваших заявлений о соединении и/или в какой таблице вы начинаете с предложения FROM, даже если логически это не повлияет на результат. Это немного отчаянный гамбит, но я определенно изменил планы выполнения, сделав это. Оптимизация запросов Oracle не всегда является рациональным процессом.

+0

Большое спасибо, Иван. Ваши советы оказались очень полезными, особенно пункты 3 и 5 (если они были пронумерованы). –

0

Вы можете использовать параметры контекста, как описано здесь: creating parameterized views in oracle11g или http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:906341500346611919 («параметризованных Просмотров с видом-vs, где условия» в случае, если они еще раз изменить URL-адреса)

Таким образом, вы можете положить ГДЕ aaa_id = SYS_CONTEXT ('my_namespace', 'aaa_id') глубоко в определении вида и использовать его как:

CREATE OR REPLACE VIEW vw_my_view AS 
WITH subquery AS (SELECT aaa_id, ... FROM table_aaa ... 
    WHERE aaa_id = SYS_CONTEXT ('my_namespace', 'aaa_id')) 
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING (...) 
; 

DBMS_SESSION.SET_CONTEXT('my_namespace', 'aaa_id', TO_CHAR(:id)); 
SELECT ... FROM vw_my_view /* this is not needed any more: WHERE aaa_id = :id */ 

Google для большего количества примеров и объяснений (поиск термина «PARAMET (е) Ризе d view in oracle ") ...

Смежные вопросы