2012-03-27 3 views
0

Я написал следующий SQL-запрос в Oracle 11g.Как сократить время выполнения следующего запроса в Oracle?

SELECT p.matchcode  pmatchcode, 
     p1.matchcode  p1matchcode, 
     p.digits   digit, 
     p1.effectivedate peff, 
     p1.expirydate pexp, 
     p.expirydate  p1exp, 
     p.tariff_id  tariff_id 
    FROM tt_matchcodes_view p1 
    JOIN tt_matchcodes_view p 
    on p.tariff_id = p1.tariff_id 
    AND p.type_id = p1.type_id 
    AND p1.Digits = p.Digits 
    AND p.matchcode <> p1.matchcode 
    AND p1.EffectiveDate < p.expirydate 
    AND (p1.expirydate IS NULL OR p1.expirydate > p.expirydate) 
    AND substr(p.matchcode, 0, length(p1.matchcode)) = p1.matchcode; 

Таблица tt_matchcodes_view имеет 71392 записей. У меня есть две индексы, созданные в этой таблице в полях matchcode and digits. Выполняется более 10 минут. В любом случае, чтобы сократить время выполнения.

Sample Таблица DATA:

MATCHCODE DIGITS DEST_ID MATCH EFFECTIVEDATE EXPIRYDATE INHERITED TARIFF_ID TYPE_ID 
1787 1787 73999 1 01/03/2012  0 22 1 
1787201 1787 73999 0 01/03/2012  -1 22 1 
1787202 1787 73999 0 01/03/2012  -1 22 1 
1787203 1787 73999 0 01/03/2012  -1 22 1 
1787204 1787 73999 0 01/03/2012  -1 22 1 
1787205 1787 73999 0 01/03/2012  -1 22 1 
1787206 1787 73999 0 01/03/2012  -1 22 1 
1787207 1787 73999 0 01/03/2012  -1 22 1 
1787208 1787 73999 0 01/03/2012  -1 22 1 
1787212 1787 73999 0 01/03/2012  -1 22 1 

Execution ПЛАН:

OPERATION OPTIONS OBJECT_NAME OBJECT_INSTANCE OPTIMIZER ID PARENT_ID DEPTH POSITION COST CARDINALITY BYTES CPU_COST IO_COST 
SELECT STATEMENT    ALL_ROWS 0  0 703 703 3 501 83322403 698 
HASH JOIN     1 0 1 1 703 3 501 83322403 698 
TABLE ACCESS FULL TT_MATCHCODES_VIEW 2  2 1 2 1 95 65498 5174342 22711001 94 
TABLE ACCESS FULL TT_MATCHCODES_VIEW 1  3 1 2 2 95 65498 5763824 22711001 94 

Thx заранее.

+0

Почему у вас есть 'substr (p.matchcode, 0, length (p1.matchcode))'? Это бессмысленно. Также как @GauravSoni упоминает, пожалуйста, отредактируйте и добавьте планы выполнения. – Sathya

+0

. Вы описываете 'tt_matchcodes_view' как таблицу, но это название предлагает что-то другое. Итак, действительно ли это таблица или это на самом деле представление? – APC

+0

Код соответствия P1 должен присутствовать в кодовом коде P. Вот почему я сохранил СУБСТР. tt_matchcodes_view - временная таблица, а не просмотр [Игнорировать имя]. –

ответ

1

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

Однако, исходя из информации, которую вы предоставили до сих пор, я не уверен, что есть лучший план, который Oracle может придумать. Индекс только для matchcode вряд ли будет полезен для этого запроса, учитывая условия на нем в предикате. Индекс на digits можно использовать, но поскольку вы присоединяетесь к таблице к себе, это, вероятно, будет менее эффективным, чем просто выполнение двух полных сканирований, так как всегда будут совпадения на digits (за исключением случаев, когда это NULL, если когда-либо).

Нам нужно знать более подробную информацию о том, какие условия в предикатах фильтруют большинство строк, чтобы сделать больше предложений. Предполагая, что основным критерием является неравенство на matchcode, вы можете получить некоторую выгоду из одного индекса (digits, matchcode) - он может потенциально присоединиться к индексу с самим собой и устранить множество строк, прежде чем идти в таблицу вообще ,

2

Ваш стол имеет более 70000 рядов. Вы выбираете все свои записи дважды и сравниваете строки на основе неравновесия. Поэтому в основном вы сравниваете каждую строку с каждой другой строкой в ​​таблице. (На самом деле не все из них, потому что не те, где TARIFF_ID или TYPE_ID или DIGITS не совпадают, но это не похоже на многие из них). Это ~ 490 000 000 сравнений. По истечении десяти минут время исполнения не кажется слишком плохим.

План объяснения показывает, что Oracle выбрал лучший план, который он может сделать. Все, что вы можете сделать, чтобы улучшить, было бы дать Oracle более полезный индекс. Компонентный индекс, который использует все столбцы в предложении where, может помочь. Что-то вроде этого:

create index super_match_idx on tt_matchcodes_view 
    (tariff_id, .type_id, digits, matchcode, expirydate, effectivedate)  

Это может дать вам два полных быстрого сканирования по индексу, который должен быть быстрее, чем два полных операций сканирования таблицы.

Кстати, вы сортируете данные, когда заполняете временную таблицу? Использование ORDER BY, которое выравнивается с индексом, улучшит коэффициент кластеризации. Таким образом, вы можете получить более быструю процедуру поиска, потому что все соответствующие строки с большей вероятностью будут находиться в смежных блоках.

Обычно я не советую сортировать строки в кучевых таблицах, но поскольку вы уже оплачиваете накладные расходы на вставку во временную таблицу, вы также можете получить столько же сока взамен.

О, и substr(p.matchcode, 0, length(p1.matchcode)) является мертвой поддавки. Смарт-ключи - это сосать! В любом случае, существует ли когда-нибудь случай, когда вызов SUBSTR() возвращает значение, которое не соответствует DIGITS? (Снова ваши данные выборки неоднозначны.) Если DIGITS relaibly идентифицирует вывод SUBTSR(), я предлагаю вам удалить эту последнюю строку.

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