Настройка производительности с предложением "ORDER BY" и "LIKE" - PullRequest
1 голос
/ 24 сентября 2010

У меня есть 2 таблицы, в которых есть много записей (скажем, и TableA, и TableB имеют около 3 000 000 записей) .vr2_input - это входные параметры varchar, вводимые пользователями, и я хочу получить самые большие 200 записей TableA из dateField, чьи stringField, как 'vr2_input'. Две таблицы объединяются следующим образом:

select * from(   
   select * from 
        TableA join TableB on TableA.id = TableB.id
        where  TableA.stringField like 'vr2_input' || '%'
        order by  TableA.dateField desc   
) where rownum < 201

Запрос медленный, я задумалась и обнаружила, что это потому, что «как» и «упорядочить по» включает в себя полное сканирование таблицы. Однако я не могу найти решение для решения проблемы. Как я могу настроить этот тип SQL? Я уже создал индекс для TableA.stringField и TableA.dateField, но как я могу использовать функцию индекса в операторе выбора? База данных оракула 10г. Большое спасибо !!

Обновление: я использую предложение iddqd, выбираю только те поля, которые хочу, и запускаю план объяснения. Завершение запроса заняло около 4 минут. IX_TableA_stringField - это имя индекса поля TableA.srv_ref. Я снова запускаю план объяснения без подсказки, план объяснения по-прежнему получает тот же результат.

EXPLAIN PLAN FOR
    select * from(
         select   
                 /*+ INDEX(TableB IX_TableA_stringField)*/ 
                  TableA.id,
                    TableA.stringField,
                    TableA.dateField,
                    TableA.someField2,
                   TableA.someField3,
            TableB.someField1,
            TableB.someField2,
            TableB.someField3,
                    from TableA 
                    join TableB  on  TableA.id=TableB.id
                    WHERE TableA.stringField  like '21'||'%'  
                 order by TableA.dateField  desc
        ) where rownum < 201

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                            
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
Plan hash value: 871807846                                                                                                                                                                                                                                                                    

--------------------------------------------------------------------------------------------------------                                                                                                                                                                           
| Id  | Operation                       | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                      
--------------------------------------------------------------------------------------------------------                                                                                                                                                                           
|   0 | SELECT STATEMENT                |                      |   200 | 24000 |  3293   (1)| 00:00:18 |                                                                                                                                                                   
|*  1 |  COUNT STOPKEY                  |                      |       |       |            |          |                                                                                                                                                                                   
|   2 |   VIEW                          |                      |  1397 |   163K|  3293   (1)| 00:00:18 |                                                                                                                                                                             
|*  3 |    SORT ORDER BY STOPKEY        |                      |  1397 | 90805 |  3293   (1)| 00:00:18 |                                                                                                                                                              
|   4 |     NESTED LOOPS                |                      |  1397 | 90805 |  3292   (1)| 00:00:18 |                                                                                                                                                                      
|   5 |      TABLE ACCESS BY INDEX ROWID| TableA       |  1397 | 41910 |   492   (1)| 00:00:03 |                                                                                                                                                 
|*  6 |       INDEX RANGE SCAN          | IX_TableA_stringField |  1397 |       |     6   (0)| 00:00:01 |                                                                                                                                                         
|   7 |      TABLE ACCESS BY INDEX ROWID| TableB      |     1 |    35 |     2   (0)| 00:00:01 |                                                                                                                                                      
|*  8 |       INDEX UNIQUE SCAN         | PK_TableB   |     1 |       |     1   (0)| 00:00:01 |                                                                                                                                                            
--------------------------------------------------------------------------------------------------------                                                                                                                                                                           

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

   1 - filter(ROWNUM<201)                                                                                                                                                                                                                                                                      
   3 - filter(ROWNUM<201)                                                                                                                                                                                                                                                                      
   6 - access("TableA"."stringField" LIKE '21%')                                                                                                                                                                                                                                                 
       filter("TableA"."stringField" LIKE '21%')                                                                                                                                                                                                                                                     
   8 - access(TableA"."id"="TableB"."id")       

Ответы [ 8 ]

3 голосов
/ 24 сентября 2010

Вы говорите, что выполнение запроса занимает около 4 минут.Вывод EXPLAIN PLAN показывает приблизительную оценку 18 секунд.Таким образом, оптимизатор, вероятно, далек от некоторых своих оценок в этом случае.(Возможно, все еще выбирается наилучший из возможных планов, но, возможно, нет.)

Первым шагом в таком случае является получение фактического плана выполнения и статистики.Запустите ваш запрос с подсказкой /*+ gather_plan_statistics */, а затем сразу же выполните select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')).

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

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

select TableA.id,
       TableA.stringField,
       TableA.dateField,
       TableA.someField2,
       TableA.someField3,
       TableB.someField1,
       TableB.someField2,
       TableB.someField3,
  from (select * from(
         select   
                  TableA.id,
                    TableA.stringField,
                    TableA.dateField,
                    TableA.someField2,
                    TableA.someField3,
                    from TableA 
                    WHERE TableA.stringField  like '21'||'%'  
                 order by TableA.dateField  desc
          )
          where rownum < 201
       ) TableA
       join TableB  on  TableA.id=TableB.id
1 голос
/ 24 сентября 2010

Вам нужно выбрать все столбцы (*)? Оптимизатор с большей вероятностью выполнит полное сканирование, если выбрать все столбцы. Если вам нужны все столбцы в выводе, вам может быть лучше выбрать идентификатор во встроенном представлении, а затем присоединиться назад, чтобы выбрать другие столбцы, что можно сделать с помощью поиска по индексу. Попробуйте запустить план объяснения для обоих случаев, чтобы увидеть, что делает оптимизатор.

0 голосов
/ 09 июля 2013

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

Взгляд: http://docs.oracle.com/cd/B28359_01/text.111/b28303/ind.htm

Спасибо

0 голосов
/ 25 сентября 2010

Вы можете создать один индекс функции для таблицы A.Это вернет 1 или 0 в зависимости от условия TableA.stringField, например 'vr2_input' ||% удовлетворен или нет.Этот индекс заставит запрос выполняться быстрее.Логика функции будет

if (substr(TableA.stringField, 1, 9) = 'vr2_input'
THEN 
    return 1;
else 
    return 0;

Использование реальных имен столбцов вместо "*" может помочь.По крайней мере, общие имена столбцов должны быть удалены.

0 голосов
/ 24 сентября 2010

Если у вас достаточно памяти, вы можете подсказать запрос для использования хеш-соединения.Не могли бы вы приложить план объяснения

0 голосов
/ 24 сентября 2010
select id from(   
   select /*+ INDEX(TableB stringField_indx)*/ TableB.id from 
        TableA join TableB on TableA.id = TableB.id
        where  TableA.stringField like 'vr2_input' || '%'
        order by  TableA.dateField desc   
) where rownum < 201

next:

SELECT * FROM TableB WHERE id iN( id from first query)

Пожалуйста, пришлите статистику и DDL этих таблиц.

0 голосов
/ 24 сентября 2010

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

Хорошим экспериментом было бы удалить объединение и проверить скорость на нем; также, если это разрешено, вы можете поместить rownum <201 в качестве предложения AND в главном запросе.Вероятно, в данный момент запрос возвращает все строки во внешний запрос, а затем он усекается? </p>

0 голосов
/ 24 сентября 2010

Создание индексов для столбцов stringField и dateField. Механизм SQL использует их автоматически.

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