SQL занимает время для выполнения - PullRequest
0 голосов
/ 09 мая 2018
Select pinv.pipeline_ref_id  Invoice_No,
 pinv.orig_company_id Company,
 pinv.orig_terminal_id Terminal,
 phwb.pipeline_ref_id HWB_No,
 ih.transport_mode Trans_Mode,
 ih.import_export_ind Business_Type,
 to_date(ms.accounting_date,'dd/mm/yy') BL_Confirm_date,
to_date(sf_get_local(pinv.pipeline_tx_status_date,pinv.status_date_tz_code),'dd/mm/yy') Inv_Void_Date,
 (pinv.pipeline_tx_status_date - ms.accounting_date) BL_Days, ih.billto_name BillTo_Name, ppi.partner_id BillTo_ID,
pinv.last_modified_by Executed_By, ih.oc_invoice_amt Invoice_Amount

From pipeline pinv

JOIN invoice_header ih ON pinv.pipeline_tx_id = ih.pipeline_tx_id
JOIN pipeline_relations prin ON pinv.pipeline_tx_id = prin.pipeline_tx_id 
JOIN pipeline phwb ON prin.rel_pipeline_tx_id = phwb.pipeline_tx_id
JOIN multisegment_status ms ON phwb.pipeline_tx_id = ms.pipeline_tx_id
JOIN pipeline_parties ppi ON ppi.partner_role = 'BT'
Where
(TRUNC(sf_get_local(pinv.pipeline_tx_status_date,pinv.status_date_tz_code)) between to_date('&1','DD-MON-YYYY:HH24:MI:SS') AND to_date('&2','DD-MON-YYYY:HH24:MI:SS'))

Я новичок в Oracle. SQL занимает часы даже для получения данных за 1 час. не могли бы вы проверить, что я делаю не так.

Также еще одна вещь, как именно это работает:

TRUNC(sf_get_local(pinv.pipeline_tx_status_date,pinv.status_date_tz_code)) between to_date('&1','DD-MON-YYYY:HH24:MI:SS') AND to_date('&2','DD-MON-YYYY:HH24:MI:SS')

Спасибо, Фуко

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Если вы положили индексы, чтобы помочь JOIN s, следующее лучшее место для поиска - это предложение WHERE.

В идеале не следует помещать столбцы поиска в функции. Размещение столбцов поиска внутри функций не позволяет эффективно использовать их индексы. (Поиск в сети SARGable.) Например, первый фрагмент здесь может работать быстрее второго, если у вас есть соответствующие индексы ...

WHERE
       myTable.dateColumn >= TRUNC(to_date('&1','DD-MON-YYYY:HH24:MI:SS'))
   AND myTable.dateColumn <  TRUNC(to_date('&2','DD-MON-YYYY:HH24:MI:SS')) + INTERVAL '1' DAY

Vs

WHERE
  TRUNC(myTable.dateColumn) BETWEEN to_date('&1','DD-MON-YYYY:HH24:MI:SS')
                                AND to_date('&2','DD-MON-YYYY:HH24:MI:SS')

Это все еще оставляет вызов функции:

sf_get_local(pinv.pipeline_tx_status_date,pinv.status_date_tz_code)

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

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

0 голосов
/ 09 мая 2018

как именно это работает

sf_get_local() - это функция в вашем приложении, а не встроенная в Oracle, поэтому вы можете посмотреть на ее источник, чтобы выяснить, что он делает, а мы нет. Тем не менее, я предполагаю, что это преобразование временной метки в UTC в местный часовой пояс. trunc() удаляет элемент времени, поэтому 2018-05-08 15:20:01.542 станет просто 2018-05-08, что кажется немного странным, если операнды выражены в форматах даты и времени с точностью до секунды.

Что касается того, почему "SQL занимает часы", нам трудно сказать. Производительность диагностики требует гораздо больше подробностей. План объяснения поможет. Узнайте больше.

Очевидные вещи, на которые нужно посмотреть:

Предложение WHERE, вероятно, не использует индекс (если только у вас нет индекса на основе функций в pipeline(trunc(sf_get_local(pipeline_tx_status_date,status_date_tz_code)). Проблема в том, что вы фильтруете по диапазону дат, так что это трудно для Оптимизатор, который сообщает об использовании индекса, - это хорошо. Если диапазон составляет час, а вы сканируете данные за пять лет, то индекс полезен. Но не в том случае, если диапазон охватывает год, а у вас есть пять лет. данные.

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

Это соединение на самом деле является CROSS JOIN :

JOIN pipeline_parties ppi ON ppi.partner_role = 'BT'

Вы не присоединяете pipeline_parties по идентификатору к любой из других таблиц в запросе. Это означает, что ваш результирующий набор будет произведением всех остальных строк, каждая строка в pipeline_parties, где partner_role = 'BT'. Может быть, это всего лишь одна строка, и в этом случае вы должны четко указать CROSS JOIN. В противном случае возврат большего количества данных, чем вам нужно, вероятно, будет еще одной причиной, по которой запрос занимает время.

Некоторые из ваших объединений выглядят так :

JOIN multisegment_status ms ON phwb.pipeline_tx_id = ms.pipeline_tx_id

Но все идет от pipeline. Вы можете помочь оптимизатору принять более разумное решение, соединив все дочерние таблицы с этой таблицей:

JOIN multisegment_status ms ON pinv.pipeline_tx_id = ms.pipeline_tx_id

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

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

...