2013-07-31 5 views
1

У меня есть ниже простой динамической запрос на выборкуOracle простой оптимизации Выберите запрос

Select RELATIONSHIP 
    from DIME_MASTER 
WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=? 

таблица имеет 1,083,701 записей. Этот запрос занимает от 11 до 12 секунд для выполнения, что дорого. Таблица DIME_MASTER имеет ACCOUNT, CARD_NUMBER INDEXES. Пожалуйста, помогите мне оптимизировать этот запрос, чтобы время выполнения запроса было меньше секунды.

+0

Ну положил один индекс на всех 3 'cin',' 'ssn' и account_number' в порядке селективности (тот, который имеет самые уникальные значения в столбце, должен быть первым). Сделайте индекс уникальным, если это возможно ... тогда динамика страшна ... Я предполагаю, вы имеете в виду, что вы меняете переменные, а не стройте запрос каждый раз. – Ben

+1

Ну, без правильных указателей, неудивительно, что это медленно ... Что вы пробовали? Что показывает план выполнения? – ppeterka

+1

** Вам нужно показать нам определения таблиц и индексов **, а также подсчет строк для каждой из таблиц. Возможно, ваши таблицы плохо определены. Возможно, индексы создаются неправильно. Возможно, у вас нет указателя на тот столбец, который, как вы думали, вы делали. Не видя определения таблиц и индексов, мы не можем сказать. Нам также нужны подсчет строк, потому что это может сильно повлиять на оптимизацию запросов. Если вы знаете, как сделать «EXPLAIN» или получить план выполнения, поместите результаты в вопрос. –

ответ

1

Посмотрите информацию предиката:

-------------------------------------- 
1 - filter(TO_NUMBER("DIME_MASTER"."SSN")=226550956 
      AND TO_NUMBER("DIME_MASTER"."ACCOUNT_NUMBER")=4425050005218650 
      AND TO_NUMBER("DIME_MASTER"."CIN")=00335093464) 

Тип ваших столбцов NVARCHAR, но параметры в запросе являются Чисел.
Оракул должен накладывать числа на строки, но иногда он не очень умный в литье.
Оракулы и гадалки не всегда правы;)

Эти отбрасывания не позволяют запросу использовать индексы.

Перепишите запрос с использованием явного преобразования в:

Select RELATIONSHIP 
    from DIME_MASTER 
WHERE CIN=to_char(?) AND SSN=to_char(?) AND ACCOUNT_NUMBER=to_char(?) 

затем запустить эту команду:

exec dbms_stats.gather_table_stats(user, 'DIME_MASTER'); 

и запустить запрос и показать нам новый план объяснить.

Не могли бы вы вставить объяснительные планы здесь, они нечитаемы,
, пожалуйста, используйте вместо этого pastebin и вставьте только ссылки здесь, спасибо.

Посмотрите на этом простом примере показывает, почему вам нужно явное приведение:

CREATE TABLE "DIME_MASTER" ( 
    "ACCOUNT_NUMBER" NVARCHAR2(16) 
); 
insert into dime_master 
select round(dbms_random.value(1, 100000)) from dual 
connect by level <= 100000; 
commit; 
create index dime_master_acc_ix on dime_master(account_number); 

explain plan for select * from dime_master 
where account_number = 123; 

select * from table(dbms_xplan.display); 

Plan hash value: 1551952897 

--------------------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |    |  3 | 54 | 70 (3)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| DIME_MASTER |  3 | 54 | 70 (3)| 00:00:01 | 
--------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter(TO_NUMBER("ACCOUNT_NUMBER")=123) 




explain plan for select * from dime_master 
where account_number = to_char(123); 

select * from table(dbms_xplan.display); 
Plan hash value: 3367829596 

--------------------------------------------------------------------------------------- 
| Id | Operation  | Name    | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |     |  3 | 54 |  1 (0)| 00:00:01 | 
|* 1 | INDEX RANGE SCAN| DIME_MASTER_ACC_IX |  3 | 54 |  1 (0)| 00:00:01 | 
--------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - access("ACCOUNT_NUMBER"=U'123') 
+0

жаль позднего ответа, прежде чем увидеть ваш ответ, я смог найти то же самое, что оракул делал to_char для числа и, следовательно, не использовал требуемые индексы и занимал больше времени для выполнения запросов. Я изменил свой запрос примерно так: – user2639553

+0

Выберите RELATIONSHIP от DIME_MASTER ГДЕ CIN =? И SSN =? И ACCOUNT_NUMBER =? и CIN, как «?%» и SSN, например «?%» и «ACCOUNT_NUMBER LIKE»?% », и он быстро начал использовать index & query. – user2639553

0

В зависимости от мощности столбцов (Всего строк/уникальных значений) - вы можете создавать растровые индексы для каждого столбца. Индексы растровых изображений очень полезны для операций and/or.

Правило большого пальца говорит, что индекс растрового изображения полезен для мощности более 10%.

create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN); 
+0

Как его использовать в Query? – user2639553

+0

Я создал 2 растровых индекса для CIN & SSN 'create bitmap index DIME_MASTER_CIN_BIX на DIME_MASTER (CIN); создать битмап-индекс DIME_MASTER_SSN_BIX на DIME_MASTER (SSN) ;, но нет улучшения в производительности. Запрос все еще занимает от 11,3 до 11,5 секунд. – user2639553

+0

DIME_MASTER СТРУКТУРА 'CREATE TABLE "Dime". "DIME_MASTER" ( "ACCOUNT_NUMBER" NVARCHAR2 (16), "APPLICATION_NUMBER" NVARCHAR2 (14), "FIRST_NAME" NVARCHAR2 (15), "LAST_NAME" NVARCHAR2 (25), "ПЛА" NVARCHAR2 (9), "КИН" NVARCHAR2 (12), ДАТА "DATE_UPDATED", "BOOK_INDICATOR" NVARCHAR2 (1), "CARD_NUMBER" NVARCHAR2 (16), "СВЯЗЬ" NVARCHAR2 (1) ) ' – user2639553

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