Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
e.kha Участник со стажем
Вступление в Клуб: 26.04.2012
|
Вт Сен 17, 2013 10:06  Медленное выполнение запроса |
|
Полезность: Нет оценки
|
Добрый день
Дано: TBL_ONE - таблица, где есть поле FIELD_ARR - массив со структурой
TBL_TWO c полями
FIELD_NAME - varchar(100)
FIELD_VALUE - varchar(200);
есть функция
Код: | function getRecord(doc_id varchar2(200)) return ref [TBL_ONE] is
p_rec ref [TBL_ONE];
begin
select a(a%id : id)
in ::[TBL_ONE], ([TBL_TWO] all : b ) all
where b.[FIELD_NAME] = 'DOC_ID' and
b.[FIELD_VALUE] = doc_id and
b%collection = a.[FIELD_ARR]
into p_rec;
return p_rec;
exception
when others then
return null;
end;
|
Данная функция вызывается из цикла. Проблема в том что у данной конструкции очень низкая производительность, где то 4 итерации цикла в секунду. Опытным путем установил что проблема в select по двум таблицам. Если сделать select по одной таблице, то все выполняется очень быстро.
Возможно увеличить производительность? |
|
 |
Volod Эксперт
Вступление в Клуб: 19.09.2007
|
Вт Сен 17, 2013 10:41   |
|
Полезность: Нет оценки
|
Ну, например, добавить в селект, по которому цикл, в виде подселекта. |
|
 |
Alkov Профи
Вступление в Клуб: 23.09.2010
|
Вт Сен 17, 2013 10:47   |
|
Полезность: 1
|
План запроса бы приложил.
Ну например индекс по b.[FIELD_VALUE] есть ?
или составной по b.[FIELD_VALUE] и b.[FIELD_NAME] ? |
|
 |
Damir Участник - экстремал
Вступление в Клуб: 29.03.2013
|
Вт Сен 17, 2013 13:27   |
|
Полезность: 1
|
Alkov пишет: | План запроса бы приложил.
Ну например индекс по b.[FIELD_VALUE] есть ?
или составной по b.[FIELD_VALUE] и b.[FIELD_NAME] ? |
Угу, еще проверить обязательно наличие индексов по полям
[TBL_TWO]. collection,
[TBL_ONE]. [FIELD_ARR]
Ну и план нужен и количество записей в таблицах.
Еще - какое количество раз дергаете эту функцию (сколько итераций в цикле)? |
|
 |
Damir Участник - экстремал
Вступление в Клуб: 29.03.2013
|
Вт Сен 17, 2013 13:45   |
|
Полезность: Нет оценки
|
Volod пишет: | Ну, например, добавить в селект, по которому цикл, в виде подселекта. |
прям по живому
Есть 2 подхода написания софта под цфт
1) Всю логику - в подзапросы. Оптимизатору легче в этом случае.
2) Всю логику - в функции. Оптимизатору срывает крышу периодически. Но поддерживать (сопровождать) 1 функцию легче, чем 80 подзапросов. |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Ср Сен 18, 2013 06:35  Re: Медленное выполнение запроса |
|
Полезность: Нет оценки
|
e.kha пишет: | Добрый день
Дано: TBL_ONE - таблица, где есть поле FIELD_ARR - массив со структурой
TBL_TWO c полями
FIELD_NAME - varchar(100)
FIELD_VALUE - varchar(200);
есть функция
Код: | function getRecord(doc_id varchar2(200)) return ref [TBL_ONE] is
p_rec ref [TBL_ONE];
begin
select a(a%id : id)
in ::[TBL_ONE], ([TBL_TWO] all : b ) all
where b.[FIELD_NAME] = 'DOC_ID' and
b.[FIELD_VALUE] = doc_id and
b%collection = a.[FIELD_ARR]
into p_rec;
return p_rec;
exception
when others then
return null;
end;
|
Данная функция вызывается из цикла. Проблема в том что у данной конструкции очень низкая производительность, где то 4 итерации цикла в секунду. Опытным путем установил что проблема в select по двум таблицам. Если сделать select по одной таблице, то все выполняется очень быстро.
Возможно увеличить производительность? |
Лично я не делал бы ограничений на field_value.
Исключение тоже выбросил бы.
Код: | type map_num is table of number index by varchar2(32767);
lm_GetRecordCache map_num;
function getRecord(doc_id varchar2(200)) return ref [TBL_ONE] is
begin
if doc_id is null then
return null;
end if;
if lm_GetRecordCache.count = 0 then
lm_GetRecordCache(0) := 0;
for (
select a(a%id : id
, b.[FIELD_VALUE] :doc_id
) in ::[TBL_ONE], ([TBL_TWO] all : b ) all
where b.[FIELD_NAME] = 'DOC_ID' and
-- b.[FIELD_VALUE] = doc_id and
b%collection = a.[FIELD_ARR]
and b.[FIELD_VALUE] is not null
) loop
lm_GetRecordCache(a.doc_id) := a.id;
end loop;
end if;
if lm_GetRecordCache.exists(doc_id) then
return lm_GetRecordCache(doc_id);
end if;
return null;
end;
|
|
|
 |
e.kha Участник со стажем
Вступление в Клуб: 26.04.2012
|
Ср Сен 18, 2013 07:05   |
|
Полезность: Нет оценки
|
to Alkov, Damir.
Были индексы
[TBL_TWO]. collection,
[TBL_ONE]. [FIELD_ARR]
и составной
[TBL_TWO]. collection
[TBL_TWO]. [FIELD_NAME]
в план делал, coast был чуть больше 1560.
С индексом b.[FIELD_VALUE] и b.[FIELD_NAME] проверю.
to Random.
Я попробую ваше предложение, но в чем профит?
когда я экспериментировал, то получалось быстро если я из селекта убирал одну таблицу, только я добавлял вторую, без всякого условия по ней, сразу начинало работать медленно. |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Ср Сен 18, 2013 11:45   |
|
Полезность: Нет оценки
|
e.kha пишет: |
to Random.
Я попробую ваше предложение, но в чем профит?
когда я экспериментировал, то получалось быстро если я из селекта убирал одну таблицу, только я добавлял вторую, без всякого условия по ней, сразу начинало работать медленно. |
Профит в том, что выполнение запроса осуществляется только 1 раз.
Попробуй.
Хотя... количество записей Код: | select a(count(1))
in ::[TBL_ONE], ([TBL_TWO] all : b ) all
where b.[FIELD_NAME] = 'DOC_ID' and
-- b.[FIELD_VALUE] = doc_id and
b%collection = a.[FIELD_ARR] | можешь сказать? |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Ср Сен 18, 2013 14:23   |
|
Полезность: Нет оценки
|
Alkov пишет: | План запроса бы приложил.
Ну например индекс по b.[FIELD_VALUE] есть ?
или составной по b.[FIELD_VALUE] и b.[FIELD_NAME] ? |
+1!
Сделай составной индекс по 3м полям: b.[FIELD_VALUE], b.[FIELD_NAME], b%collection.
Колекшн в индексе нужен для того, чтобы оракл все тянул из индекса и не лез в данные. |
|
 |
e.kha Участник со стажем
Вступление в Клуб: 26.04.2012
|
Чт Сен 19, 2013 02:05   |
|
Полезность: Нет оценки
|
Господа, огромное вам спасибо!
Помогло след.
Индекс
[TBL_ONE]. [FIELD_ARR]
Индекс
[TBL_TWO]. collection
Индекс
[TBL_TWO].[FIELD_VALUE] и [TBL_TWO].[FIELD_NAME].
Работает, как взрыв!
to maestro
Я сделал индекс как вы посоветовали, но почему то
один индекс по трем полям работает значительно медленнее чем
два индекса по
b%collection.
и b.[FIELD_NAME], b.[FIELD_VALUE]
Почему, не знаю |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Чт Сен 19, 2013 07:58   |
|
Полезность: Нет оценки
|
e.kha пишет: |
Почему, не знаю |
План в студию! |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Чт Сен 19, 2013 08:04   |
|
Полезность: 1
|
e.kha пишет: | Почему, не знаю |
Давай устроим гонки! Выполни в SQLPlus следующее.
Код: |
SQL> alter system flush shared_pool;
SQL> alter system flush buffer_cache;
SQL> set timing on
SQL> set autot traceonly
SQL> <%Сюда вставляешь запрос%>
SQL> /
|
Запускаешь такую штуку для запросов с разными индексами и статистику выкладываешь сюда!
Ну и сам посмотри, кто по цифрам лучше! |
|
 |
e.kha Участник со стажем
Вступление в Клуб: 26.04.2012
|
Чт Сен 19, 2013 08:22   |
|
Полезность: Нет оценки
|
to maestro
Индекс
[TBL_ONE]. [FIELD_ARR]
Индекс
b.[FIELD_VALUE], b.[FIELD_NAME], b%collection
План
Код: | ADMIN SELECT STATEMENT Cost=18
2.1 NESTED LOOPS
3.1 NESTED LOOPS
4.1 INDEX(RANGE SCAN) - IDX_Z#TBL_TWO_CL_ID_FN_FV(INDEX)
4.2 INDEX(UNIQUE SCAN) - IDX_Z#TBL_ONE_FIELD_ARR(INDEX (UNIQUE))
3.2 TABLE ACCESS(BY INDEX ROWID) - Z#TBL_ONE(TABLE)
|
Индекс
[TBL_ONE]. [FIELD_ARR]
Индекс
[TBL_TWO]. collection
Индекс
[TBL_TWO].[FIELD_VALUE] и [TBL_TWO].[FIELD_NAME].
План
Код: | ADMIN SELECT STATEMENT Cost=15
2.1 NESTED LOOPS
3.1 NESTED LOOPS
4.1 TABLE ACCESS(BY INDEX ROWID) - Z#TBL_TWO(TABLE)
5.1 INDEX(RANGE SCAN) - IDX_Z#TBL_TWO_FN_FV(INDEX)
4.2 INDEX(UNIQUE SCAN) - IDX_Z#TBL_ONE_FIELD_ARR(INDEX (UNIQUE))
3.2 TABLE ACCESS(BY INDEX ROWID) - Z#TBL_ONE(TABLE) |
Если я правильно эти планы сделал, вообще не копенгаген в этом
Я устраивал гонки, по простому время начал выполнения главного цилка и окончания, так и пришел к выводу... |
|
 |
e.kha Участник со стажем
Вступление в Клуб: 26.04.2012
|
Чт Сен 19, 2013 08:30   |
|
Полезность: Нет оценки
|
Random пишет: | Хотя... количество записей Код: | select a(count(1))
in ::[TBL_ONE], ([TBL_TWO] all : b ) all
where b.[FIELD_NAME] = 'DOC_ID' and
-- b.[FIELD_VALUE] = doc_id and
b%collection = a.[FIELD_ARR] | можешь сказать? |
В в каждой коллекции где то 30 записей,
этот селект выбирает только один результат,
наверно корректней тут locate использовать.. |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Чт Сен 19, 2013 09:14   |
|
Полезность: Нет оценки
|
ИМХО, первый план лучше.
Отсутствует строка
Код: |
4.1 TABLE ACCESS(BY INDEX ROWID) - Z#TBL_TWO(TABLE)
|
А значит Оракл не лезет в таблицу z#TBL_TWO.
Странно, что у него стоимость больше. Интересно, что статистика говорит? Выполни plz запросы в SQLplus, как я писал выше. |
|
 |
|