Oracle SQL 优化
Oracle SQL Optimization
我正在为客户创建报告以检索发票和他们的运送地点。目前查询速度非常慢,如果有人可以建议如何优化查询,我将不胜感激。我在查询中确实有很多外部联接,我相信这可能是问题所在。
如有任何建议,我们将不胜感激。
SELECT
b.operating_unit,
b.trading_partner,
b.invoice_date,
b.type,
b.gl_date,
b.invoice_num,
b.invoice_id,
b.quantity,
b.unit_price,
b.uom,
b.invoice_currency_code,
b.payment_method_code,
b.terms,
b.ITEM_DESCRIPTION,
b.LINE_NUMBER,
b.item_code,
b.VAT_CODE,
b.amount,
b.invoice_amount,
b.vat_amount,
b.discount_amount,
b.price_variance,
b.total_amount,
b.status,
b.ship_to_location
FROM(
SELECT
a.operating_unit,
a.trading_partner,
a.invoice_date,
a.type,
a.gl_date,
a.invoice_num,
a.invoice_id,
a.quantity,
ROUND(a.unit_price,2) unit_price,
a.uom,
a.invoice_currency_code,
a.payment_method_code,
a.terms,
a.LINE_NUMBER,
a.ITEM_DESCRIPTION,
a.item_code,
a.VAT_CODE,
--CASE WHEN a.status = 'CANCELLED' THEN NULL
--ELSE a.VAT_CODE END AS VAT_CODE,
sum(a.AMOUNT) amount,
a.invoice_amount,
sum(a.vat_amount) vat_amount,
sum(a.discount_amount) discount_amount,
sum(a.price_variance) price_variance,
sum(a.total_amount) total_amount,
CASE WHEN a.status = 'FULLY' THEN 'Fully Applied'
WHEN a.status = 'UNAPPROVED' THEN 'Unvalidated'
WHEN a.status = 'NEEDS REAPPROVAL' THEN 'Needs Revalidation'
WHEN a.status = 'APPROVED' THEN 'Validated'
WHEN a.status = 'NEVER APPROVED' THEN 'Never Validated'
WHEN a.status = 'CANCELLED' THEN 'Cancelled'
WHEN a.status = 'UNPAID' THEN 'Unpaid'
WHEN a.status = 'AVAILABLE' THEN 'Available'
END AS status,
a.ship_to_location
from(
Select
hz.name operating_unit,
aia.INVOICE_TYPE_LOOKUP_CODE type,
aps.vendor_name trading_partner,
aia.INVOICE_DATE,
aia.gl_date,
aia.invoice_num,
aia.INVOICE_AMOUNT,
aida.invoice_id,
APIDA.LINE_NUMBER,
APIDA.QUANTITY_INVOICED QUANTITY,
APIDA.UNIT_PRICE,
APIDA.UOM,
aia.INVOICE_CURRENCY_CODE,
aia.PAYMENT_METHOD_CODE,
apt.name terms,
APIDA.ITEM_DESCRIPTION,
APIDA.ITEM_CODE,
case when apida.line_type_lookup_code <> 'IPV' THEN APIDA.AMOUNT ELSE 0 END AS AMOUNT,
--case when aida.line_type_lookup_code = 'REC_TAX' THEN aida.RECOVERY_RATE_NAME END AS VAT_CODE,
APIDA.VAT_CODE,
APIDA.VAT_AMOUNT,
0 DISCOUNT_AMOUNT,
case when apida.line_type_lookup_code = 'IPV' THEN APIDA.AMOUNT ELSE 0 END AS PRICE_VARIANCE,
APIDA.TOTAL_AMOUNT,
APPS.AP_INVOICES_PKG.GET_APPROVAL_STATUS
(
aia.INVOICE_ID
,aia.INVOICE_AMOUNT
,aia.PAYMENT_STATUS_FLAG
,aia.INVOICE_TYPE_LOOKUP_CODE
) status,
APIDA.SHIP_TO_LOCATION
--b.description ship_to_location
from (SELECT AILA.INVOICE_ID, AILA.LINE_TYPE_LOOKUP_CODE, AILA.LINE_NUMBER, aila.TAX_CLASSIFICATION_CODE VAT_CODE, AILA.QUANTITY_INVOICED, AILA.UNIT_PRICE, AILA.UNIT_MEAS_LOOKUP_CODE UOM, X.invoice_distribution_id, X.Description ITEM_DESCRIPTION, msi.segment1 item_code, NVL(X.AMOUNT, 0) AMOUNT, NVL(B.TAX_AMOUNT,0) VAT_AMOUNT, (NVL(X.AMOUNT, 0) + NVL(B.TAX_AMOUNT,0)) TOTAL_AMOUNT,HR.DESCRIPTION SHIP_TO_LOCATION
FROM ap_invoice_lines_all aila, ap_invoice_distributions_all X, MTL_SYSTEM_ITEMS msi, hr_locations hr,
(SELECT A.INVOICE_ID, A.LINE_TYPE_LOOKUP_CODE, A.INVOICE_LINE_NUMBER, A.CHARGE_APPLICABLE_TO_DIST_ID, SUM(A.AMOUNT) TAX_AMOUNT
FROM ap_invoice_distributions_all A
WHERE 1=1
AND A.LINE_TYPE_LOOKUP_CODE = 'REC_TAX'
GROUP BY A.INVOICE_ID, A.LINE_TYPE_LOOKUP_CODE, A.INVOICE_LINE_NUMBER, A.CHARGE_APPLICABLE_TO_DIST_ID) B
WHERE AILA.INVOICE_ID = X.INVOICE_ID(+)
AND X.INVOICE_ID = B.INVOICE_ID(+)
AND X.invoice_distribution_id = B.CHARGE_APPLICABLE_TO_DIST_ID(+)
and msi.inventory_item_id(+) = aila.inventory_item_id
AND AILA.SHIP_TO_LOCATION_ID = HR.SHIP_TO_LOCATION_ID
and aila.line_number = X.INVOICE_LINE_NUMBER(+)
AND AILA.LINE_TYPE_LOOKUP_CODE != 'REC_TAX' AND AILA.LINE_TYPE_LOOKUP_CODE != 'NONREC_TAX'
--AND AILA.INVOICE_ID = '10T52233547'
)APIDA,
ap_invoice_distributions_all aida, ap_invoices_all aia, ap_suppliers aps, ap_terms apt, hr_organization_units hz
where aia.invoice_id = aida.invoice_id(+)
and aia.invoice_id = APIDA.invoice_id(+)
and aps.vendor_id = aia.vendor_id
and apt.term_id = aia.terms_id
and hz.ORGANIZATION_ID = aia.org_id
--and aia.invoice_NUM = '123456'
--and aida.LINE_TYPE_LOOKUP_CODE = 'REC_TAX'
/* Parameters */
and hz.ORGANIZATION_ID between NVL(:p_operating_unit_from, hz.ORGANIZATION_ID) and NVL(:p_operating_unit_to, hz.ORGANIZATION_ID)
and aia.INVOICE_DATE between NVL(:p_invoice_date_from, aia.INVOICE_DATE) and NVL(:p_invoice_date_to, aia.INVOICE_DATE)
and aps.vendor_id between NVL(:p_trading_partner_from, aps.vendor_id) and NVL(:p_trading_partner_to, aps.vendor_id)
and aia.gl_date between NVL(:p_gl_date_from, aia.gl_date) and NVL(:p_gl_date_to, aia.gl_date)
order by hz.name, aps.vendor_name, APIDA.SHIP_TO_LOCATION, APIDA.ITEM_DESCRIPTION)a
group by a.operating_unit,
a.trading_partner,
a.invoice_date,
a.gl_date,
a.invoice_num,
a.invoice_amount,
a.invoice_id,
a.invoice_currency_code,
a.payment_method_code,
a.terms,
a.ITEM_DESCRIPTION,
a.item_code,
a.VAT_CODE,
a.quantity,
a.unit_price,
a.LINE_NUMBER,
a.uom,
a.status,
a.type,
a.ship_to_location)b
order by b.operating_unit, b.trading_partner, b.ship_to_location, b.invoice_date, b.gl_date, b.invoice_num, b.LINE_NUMBER
我是 Oracle 的新手 SQL。我做了调查,问题不在于外部连接,而在于不同的连接。它必须对大量数据进行分组和排序,这会导致延迟。
我必须重新编写此代码并避免使用 DISTINCT。当我有解决方案时,我会post在这里供其他像我这样的新手学习新东西。
您在子查询中使用了 ORDER BY
,它没有任何作用,因此您应该将其删除。如果优化器尚未注意到并忽略它,这将加快查询速度。
您使用的以逗号分隔的连接语法在 1980 年代是标准的,但现在被认为容易出错且难以阅读。为了可读性和可维护性,您可能希望将其替换为显式连接(例如 INNER JOIN
和 LEFT OUTER JOIN
)。但是,我在您的连接中没有看到任何错误,因此除此之外您将一无所获。
最外面的查询是多余的,但不应导致任何速度下降。所以也没问题。
这只是一个相当复杂的查询,包含一些外连接和两个 group by 子句。没有明显的错误。检查您的 where 子句中使用的列是否有索引。您可能还需要一些复合索引。我希望所有 ID 都已编入索引。我建议添加以下三个索引:
- ap_invoice_lines_all(invoice_id, line_number)
- ap_invoice_distributions_all(invoice_id, invoice_line_number)
- ap_invoice_distributions_all(line_type_lookup_code)
我正在为客户创建报告以检索发票和他们的运送地点。目前查询速度非常慢,如果有人可以建议如何优化查询,我将不胜感激。我在查询中确实有很多外部联接,我相信这可能是问题所在。
如有任何建议,我们将不胜感激。
SELECT
b.operating_unit,
b.trading_partner,
b.invoice_date,
b.type,
b.gl_date,
b.invoice_num,
b.invoice_id,
b.quantity,
b.unit_price,
b.uom,
b.invoice_currency_code,
b.payment_method_code,
b.terms,
b.ITEM_DESCRIPTION,
b.LINE_NUMBER,
b.item_code,
b.VAT_CODE,
b.amount,
b.invoice_amount,
b.vat_amount,
b.discount_amount,
b.price_variance,
b.total_amount,
b.status,
b.ship_to_location
FROM(
SELECT
a.operating_unit,
a.trading_partner,
a.invoice_date,
a.type,
a.gl_date,
a.invoice_num,
a.invoice_id,
a.quantity,
ROUND(a.unit_price,2) unit_price,
a.uom,
a.invoice_currency_code,
a.payment_method_code,
a.terms,
a.LINE_NUMBER,
a.ITEM_DESCRIPTION,
a.item_code,
a.VAT_CODE,
--CASE WHEN a.status = 'CANCELLED' THEN NULL
--ELSE a.VAT_CODE END AS VAT_CODE,
sum(a.AMOUNT) amount,
a.invoice_amount,
sum(a.vat_amount) vat_amount,
sum(a.discount_amount) discount_amount,
sum(a.price_variance) price_variance,
sum(a.total_amount) total_amount,
CASE WHEN a.status = 'FULLY' THEN 'Fully Applied'
WHEN a.status = 'UNAPPROVED' THEN 'Unvalidated'
WHEN a.status = 'NEEDS REAPPROVAL' THEN 'Needs Revalidation'
WHEN a.status = 'APPROVED' THEN 'Validated'
WHEN a.status = 'NEVER APPROVED' THEN 'Never Validated'
WHEN a.status = 'CANCELLED' THEN 'Cancelled'
WHEN a.status = 'UNPAID' THEN 'Unpaid'
WHEN a.status = 'AVAILABLE' THEN 'Available'
END AS status,
a.ship_to_location
from(
Select
hz.name operating_unit,
aia.INVOICE_TYPE_LOOKUP_CODE type,
aps.vendor_name trading_partner,
aia.INVOICE_DATE,
aia.gl_date,
aia.invoice_num,
aia.INVOICE_AMOUNT,
aida.invoice_id,
APIDA.LINE_NUMBER,
APIDA.QUANTITY_INVOICED QUANTITY,
APIDA.UNIT_PRICE,
APIDA.UOM,
aia.INVOICE_CURRENCY_CODE,
aia.PAYMENT_METHOD_CODE,
apt.name terms,
APIDA.ITEM_DESCRIPTION,
APIDA.ITEM_CODE,
case when apida.line_type_lookup_code <> 'IPV' THEN APIDA.AMOUNT ELSE 0 END AS AMOUNT,
--case when aida.line_type_lookup_code = 'REC_TAX' THEN aida.RECOVERY_RATE_NAME END AS VAT_CODE,
APIDA.VAT_CODE,
APIDA.VAT_AMOUNT,
0 DISCOUNT_AMOUNT,
case when apida.line_type_lookup_code = 'IPV' THEN APIDA.AMOUNT ELSE 0 END AS PRICE_VARIANCE,
APIDA.TOTAL_AMOUNT,
APPS.AP_INVOICES_PKG.GET_APPROVAL_STATUS
(
aia.INVOICE_ID
,aia.INVOICE_AMOUNT
,aia.PAYMENT_STATUS_FLAG
,aia.INVOICE_TYPE_LOOKUP_CODE
) status,
APIDA.SHIP_TO_LOCATION
--b.description ship_to_location
from (SELECT AILA.INVOICE_ID, AILA.LINE_TYPE_LOOKUP_CODE, AILA.LINE_NUMBER, aila.TAX_CLASSIFICATION_CODE VAT_CODE, AILA.QUANTITY_INVOICED, AILA.UNIT_PRICE, AILA.UNIT_MEAS_LOOKUP_CODE UOM, X.invoice_distribution_id, X.Description ITEM_DESCRIPTION, msi.segment1 item_code, NVL(X.AMOUNT, 0) AMOUNT, NVL(B.TAX_AMOUNT,0) VAT_AMOUNT, (NVL(X.AMOUNT, 0) + NVL(B.TAX_AMOUNT,0)) TOTAL_AMOUNT,HR.DESCRIPTION SHIP_TO_LOCATION
FROM ap_invoice_lines_all aila, ap_invoice_distributions_all X, MTL_SYSTEM_ITEMS msi, hr_locations hr,
(SELECT A.INVOICE_ID, A.LINE_TYPE_LOOKUP_CODE, A.INVOICE_LINE_NUMBER, A.CHARGE_APPLICABLE_TO_DIST_ID, SUM(A.AMOUNT) TAX_AMOUNT
FROM ap_invoice_distributions_all A
WHERE 1=1
AND A.LINE_TYPE_LOOKUP_CODE = 'REC_TAX'
GROUP BY A.INVOICE_ID, A.LINE_TYPE_LOOKUP_CODE, A.INVOICE_LINE_NUMBER, A.CHARGE_APPLICABLE_TO_DIST_ID) B
WHERE AILA.INVOICE_ID = X.INVOICE_ID(+)
AND X.INVOICE_ID = B.INVOICE_ID(+)
AND X.invoice_distribution_id = B.CHARGE_APPLICABLE_TO_DIST_ID(+)
and msi.inventory_item_id(+) = aila.inventory_item_id
AND AILA.SHIP_TO_LOCATION_ID = HR.SHIP_TO_LOCATION_ID
and aila.line_number = X.INVOICE_LINE_NUMBER(+)
AND AILA.LINE_TYPE_LOOKUP_CODE != 'REC_TAX' AND AILA.LINE_TYPE_LOOKUP_CODE != 'NONREC_TAX'
--AND AILA.INVOICE_ID = '10T52233547'
)APIDA,
ap_invoice_distributions_all aida, ap_invoices_all aia, ap_suppliers aps, ap_terms apt, hr_organization_units hz
where aia.invoice_id = aida.invoice_id(+)
and aia.invoice_id = APIDA.invoice_id(+)
and aps.vendor_id = aia.vendor_id
and apt.term_id = aia.terms_id
and hz.ORGANIZATION_ID = aia.org_id
--and aia.invoice_NUM = '123456'
--and aida.LINE_TYPE_LOOKUP_CODE = 'REC_TAX'
/* Parameters */
and hz.ORGANIZATION_ID between NVL(:p_operating_unit_from, hz.ORGANIZATION_ID) and NVL(:p_operating_unit_to, hz.ORGANIZATION_ID)
and aia.INVOICE_DATE between NVL(:p_invoice_date_from, aia.INVOICE_DATE) and NVL(:p_invoice_date_to, aia.INVOICE_DATE)
and aps.vendor_id between NVL(:p_trading_partner_from, aps.vendor_id) and NVL(:p_trading_partner_to, aps.vendor_id)
and aia.gl_date between NVL(:p_gl_date_from, aia.gl_date) and NVL(:p_gl_date_to, aia.gl_date)
order by hz.name, aps.vendor_name, APIDA.SHIP_TO_LOCATION, APIDA.ITEM_DESCRIPTION)a
group by a.operating_unit,
a.trading_partner,
a.invoice_date,
a.gl_date,
a.invoice_num,
a.invoice_amount,
a.invoice_id,
a.invoice_currency_code,
a.payment_method_code,
a.terms,
a.ITEM_DESCRIPTION,
a.item_code,
a.VAT_CODE,
a.quantity,
a.unit_price,
a.LINE_NUMBER,
a.uom,
a.status,
a.type,
a.ship_to_location)b
order by b.operating_unit, b.trading_partner, b.ship_to_location, b.invoice_date, b.gl_date, b.invoice_num, b.LINE_NUMBER
我是 Oracle 的新手 SQL。我做了调查,问题不在于外部连接,而在于不同的连接。它必须对大量数据进行分组和排序,这会导致延迟。
我必须重新编写此代码并避免使用 DISTINCT。当我有解决方案时,我会post在这里供其他像我这样的新手学习新东西。
您在子查询中使用了 ORDER BY
,它没有任何作用,因此您应该将其删除。如果优化器尚未注意到并忽略它,这将加快查询速度。
您使用的以逗号分隔的连接语法在 1980 年代是标准的,但现在被认为容易出错且难以阅读。为了可读性和可维护性,您可能希望将其替换为显式连接(例如 INNER JOIN
和 LEFT OUTER JOIN
)。但是,我在您的连接中没有看到任何错误,因此除此之外您将一无所获。
最外面的查询是多余的,但不应导致任何速度下降。所以也没问题。
这只是一个相当复杂的查询,包含一些外连接和两个 group by 子句。没有明显的错误。检查您的 where 子句中使用的列是否有索引。您可能还需要一些复合索引。我希望所有 ID 都已编入索引。我建议添加以下三个索引:
- ap_invoice_lines_all(invoice_id, line_number)
- ap_invoice_distributions_all(invoice_id, invoice_line_number)
- ap_invoice_distributions_all(line_type_lookup_code)