Oracle, низкая производительность при использовании суб-выбора - PullRequest
1 голос
/ 02 июня 2010

У меня очень медленное представление, если вы выбираете все строки. Но если я выберу подмножество (предоставив идентификатор в предложении where), производительность будет очень хорошей. Я не могу жестко закодировать идентификатор, поэтому я создаю дополнительный элемент, чтобы получить идентификатор из другой таблицы. Дополнительный выбор возвращает только один идентификатор. Теперь производительность очень низкая, и кажется, что Oracle оценивает весь вид перед использованием предложения where. Можно ли как-то помочь Oracle, чтобы SQL 2 и 3 имели одинаковую производительность? Я использую Oracle 10g

1 медленный

выберите * из ci.my_slow_view

2 быстро

выберите * из ci.my_slow_view, где id = 1;

3 медленно

select * from ci.my_slow_view, где id (выбрать id из active_ids)

Ответы [ 4 ]

2 голосов
/ 03 июня 2010

Как насчет

select * from ci.my_slow_view where id = (select id from active_ids)

Замена «in» на «=» скажет Oracle, что вы ожидаете, что «select id from active_ids» вернет только одну строку.

2 голосов
/ 02 июня 2010

Это ожидаемое поведение ... 3 медленный, потому что Oracle выполнит «полное сканирование таблицы», что означает, что ваши индексы там не помогают (ваше предложение where не содержит никакой константы или диапазона и является неограниченным, что означает, что независимо от того, какой индекс вы используете, все строки потенциально кандидаты на условие соединения.

Возможные улучшения: Во-первых, проверьте правильность индексов в столбцах join / pk (id в my_slow_view и active_ids). Это необходимо для второго шага: Во-вторых, сгенерируйте статистику таблицы для вашей таблицы и представлений, что даст возможность оптимизатору кеш-памяти Oracle. (Это должно работать, потому что предполагается, что ваша таблица active_ids достаточно мала, чтобы быть полностью в памяти.)

Второй подход: Напишите хранимую процедуру в PL / SQL, где ваш идентификатор является входным параметром, и переписайте свой SQL, чтобы он использовал связанный параметр.

Это должно дать вам необходимую гибкость (без жестко заданных идентификаторов) и скорость самого быстрого запроса.

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

Или:

select * from ci.my_slow_view, active_ids
where my_slow_view.id = active_ids.id;
0 голосов
/ 02 июня 2010

Я не могу жестко закодировать идентификатор, поэтому я создаю суб выберите, чтобы получить идентификатор от другого Таблица. Дополнительный выбор возвращает только один ID.

Скорее всего, поможет сбор статистики для небольшой таблицы (хотя она содержит одну строку), поскольку это должно помочь Oracle понять, что она мала, и побудить ее использовать индекс по ID.

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

SQL>  variable id number
SQL>  exec :id := 1;
SQL>  select * from ci.my_slow_view where id = :id ;
SQL>  exec :id := 2;
SQL>  select * from ci.my_slow_view where id = :id ;

Детали реализации этого зависят от среды, в которой вы разрабатываете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...