2013-09-04 5 views
2

У меня есть представление, которое содержит все данные, относящиеся к сотруднику. у него было около 350 тыс. Записей. Мне нужно создать функцию поиска имени. Это позволит получить все данные, соответствующие введенному ключевому слову.Оптимизация поиска строк в oracle

Производительность запроса очень медленная, для получения данных требуется 15-20 секунд. Экономически 15000

Мой запрос:

SELECT   H.PERSON_ID, 
        B.EMPLOYEE_ID, 
        INITCAP(B.FIRST_NAME) EMP_FNAME, 
        INITCAP(B.MIDDLE_NAME) EMP_MNAME, 
        INITCAP(B.LAST_NAME) EMP_LNAME, 
        B.EMPLOYEE_TYPE PERSON_DESC, 
        B.EMPLOYMENT_STATUS STATUS_TYPE, 
        EA.BASE_BRANCH 

       FROM EMPLOYEE_BASIC_DTLS B, 
        EMP_ASSIGNMENT_DTLS_MV EA, 
        EMPLOYEE_HIS_DEPNDENT_TBL H 
      WHERE B.PERSON_ID = EA.PERSON_ID 
       AND B.PERSON_ID = H.PERSON_ID 
       AND ((UPPER(B.FIRST_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%')) OR 
        (UPPER(B.MIDDLE_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%')) OR 
        (UPPER(B.LAST_NAME) LIKE 
        ('%' || V_SEARCH_PARAM1 || '%'))) 
       AND TRUNC(SYSDATE) BETWEEN EA.EFFECTIVE_START_DATE AND 
        EA.EFFECTIVE_END_DATE 
       AND UPPER(H.RELATIONSHIP_CODE) = 'A'; 

С EMPLOYEE_BASIC_DTLS вид я не могу использовать индексацию.

+2

Вам действительно нужен главный шаблон во всех ваших выражениях? У вас действительно есть люди, которые хотят найти «Justin Cave», когда они набирают «stin»? Ведущая дикая карта будет препятствовать использованию любых индексов на базовой таблице. Если вы действительно хотите создать основной шаблон, вы можете использовать индекс Oracle Text и реорганизовать свой запрос на использование 'CONTAINS', а не' LIKE', но это также довольно сложно. –

ответ

1

Хотя это правда, вы не можете поместить индекс в представление, вы можете, конечно, поместить индексы в базовые таблицы. Однако, как отмечено @JustinCave, даже если вы добавляете индексы в соответствующие таблицы, этот запрос по-прежнему не будет использовать их из-за использования LIKE. Кроме того, поскольку функция UPPER применяется к столбцам FIRST_NAME, MIDDLE_NAME и LAST_NAME, вам необходимо определить ваши индексы в качестве функциональных индексов. Например, если «реальные» таблицы доступны по EMPLOYEE_BASIC_TABLE зрения называется EMPLOYEES можно определить индекс-функцию на FIRST_NAME колонке, как

CREATE INDEX EMPLOYEES_UPPER_FIRST_NAME ON EMPLOYEES (UPPER(FIRST_NAME)); 

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

Если вы хотите исследовать индексы Oracle Text, вы можете найти документацию here. Я думаю, вы обнаружите, что он больше подходит для документирования или документирования фрагментарных индексов, но, возможно, это даст вам некоторые идеи.

Делитесь и наслаждайтесь.

+2

Было бы точнее сказать, что запрос * может * использовать индекс - Oracle может быстро выполнять полное сканирование индексов. –

+0

Спасибо всем за ответ, на самом деле я ищу универсальный поиск, так что LIKE - единственный вариант, и в отношении индекса моя таблица имеет растровое изображение, индексированное по соответствующим столбцам. Я действительно был бы набит, если кто-нибудь может предложить хорошую альтернативу. –

+1

Мне любопытно - почему вы решили использовать растровые индексы на этих столбцах? –

1

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

Что вы можете сделать, это ускорить сканирование.

Вы можете ускорить сканирование полного стола, распараллеливая его через/* + parallel (EMPLOYEE_BASIC_TABLE, 4) */например. (Это был бы мой совет здесь.)

Или вы можете избежать полного сканирования таблицы, указав один индекс на столбец, хорошо зная, что существует много многократно используемых имен, так что каждое имя сканируется только один раз. Затем вы будете использовать функциональные ключи в базовой таблице, как предлагает Боб Джарвис, потому что вы используете верхнюю функцию для любого имени. Самый быстрый был бы комбинированным индексом:

create bitmap index idx_name_search on EMPLOYEE_BASIC_TABLE (upper(first_name || '|' || middle_name || '|' || last_name)) 

поэтому есть только один индекс для поиска. (Вам нужно было бы использовать именно это выражение в своем запросе, конечно: WHERE upper (first_name || '|' || middle_name || '|' || last_name), например '% JOHN%'.) Но все же вы не знаете, t знать, что будет искать заранее, и поскольку «% JOHN%» может влиять только на 2% ваших данных таблицы, «% E%» может повлиять на 80%. Оптимизатор никогда не узнает. Вы могли бы, по крайней мере, догадаться, и должны иметь разные операторы select, один с полным подсказкой таблицы, который вы будете использовать, если строка поиска содержит по крайней мере три буквы и одну с подсказкой индекса, которую вы использовали бы иначе, например.

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

+0

Как только вы изменили свой код: действительно ли EA.EFFECTIVE_START_DATE и EA.EFFECTIVE_END_DATE значительно сократили набор результатов? UPPER (H.RELATIONSHIP_CODE) = 'A'? Является ли EMPLOYEE_HIS_DEPNDENT_TBL большой таблицей? Возможно, вам понадобится индекс на основе функции на UPPER (RELATIONSHIP_CODE). И, поскольку это код: действительно ли нужна функция UPPER? Действительно ли поле действительно соответствует как «А», так и «а», хотя они означают одно и то же? Тогда вы можете изменить это. –

+0

EA.EFFECTIVE_END_DATE есть, потому что в EMP_ASSIGNMENT_DTLS_MV у меня есть несколько записей wrt person_id. EMPLOYEE_HIS_DEPNDENT_TBL содержит 4 файла lac arnd no Только 'A' принимается не 'a'. –

+0

Большое спасибо за то, что вы задали этот вопрос. Можете ли вы немного рассказать, как я могу рассчитать свой запрос? –

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