資産モジュールにはカスタマイズされたレポートがあり、FA_ 関連テーブルと補助元帳 XLA を通じて資産モジュール情報と会計情報をクエリします。最適化する前は、1 つの資産アカウント セットの単一の資産アカウントのデータを実行するのに 1 時間かかります。 SQL の最適化と書き換え後、1 秒ほどで実行されます。この記事では、比較的簡単な手段を使用して、最適化する方法を段階的に分析します。
核となる指導的イデオロギー
- クエリのデータ範囲を可能な限り絞り込む
- 小さなテーブルを使用して大きなテーブルを駆動する
パフォーマンス SQL の位置付け
これは大規模な pkg パッケージであり、数百行または数千行のコードが含まれる可能性があります。問題の原因となっているコード部分をすばやく特定し、レポート速度の低下を引き起こす方法を確認するには、Oracle に付属する分析ツール DBMS_HPROF を使用する必要があります。概要と使用法については、
「ORACLE パフォーマンスの最適化 - DBMS_HPROF」の記事を参照してください。
最適化前のSQL
前のステップでいくつかの簡単なコマンドを実行した後、パフォーマンス SQL を配置しました。これは非常によく似た構造を持つ UNION SQL です。ここでは例として一部のみを取り上げます。
--该sql是一个报表sql,还有几个参数条件,跟此次优化无关,已经过滤掉
SELECT a.asset_id,
to_char(h.transaction_date_entered, 'yyyy-mm-dd hh24:mi:ss'),
to_char(xe.transaction_date, 'yyyy-mm-dd'),
b.book_type_code,
a.asset_number,
a.description,
c.segment1,
c.segment2,
b.original_cost amount,
'增加' trans_type
FROM fa_transaction_headers h,
fa_additions_vl a,
fa_books b,
fa_categories c,
xla_transaction_entities xte,
xla_events xe,
fa_asset_invoices i
WHERE a.asset_id = h.asset_id
AND b.asset_id = a.asset_id
AND c.category_id = a.asset_category_id
AND h.book_type_code = b.book_type_code
AND i.asset_id = a.asset_id
AND i.po_vendor_id = i.po_vendor_id
AND b.date_ineffective IS NULL
AND h.transaction_type_code = 'ADDITION'
AND h.transaction_header_id = xte.source_id_int_1
AND xte.entity_id = xe.entity_id
アイデアの処理
データ分析(業務と連動しない)
EBS テーブルの構造とビジネスに精通しておらず、純粋に技術的な観点から分析するとします。
この SQL は複雑なものではなく、テーブル数は 7 つだけであり、FA_ で始まる関連テーブルのデータ規模は統計的にみると数万程度と小規模なテーブルです。XLA_ で始まるテーブルは数百万から数千万の大きなテーブルです。
関連テーブルのインデックス (ここでは大きなテーブルのインデックスと構造に焦点を当てます) を確認した結果、XLA_ 関連テーブルはフィールド application_id によってパーティション化されているパーティション テーブルであることがわかりましたが、パーティション制限は上記の SQL クエリの後、この SQL が取得した application_id はまったく同じで、どちらも 140 であることがわかりました。私は 1 ~ 2 年の経験を持つ EBS 技術コンサルタントから学びました (ここでは、理解していないと仮定します) EBS ビジネスとテーブル構造についてはまったく理解しておらず、EBS テクノロジーについて少しの経験があるすべてのコンサルタントは、このフィールドがビジネス モジュールのフィールド ID であることを知っています)。実際、この SQL はアセット モジュールとxla_ で始まるテーブルには、ビジネス モジュールの application_id フィールドがあり、資産モジュールに対応する application_id は 140 であり、それ以外の値はありません。
次に、パーティション テーブルの機能を利用し、パーティション制限を追加し、大きなテーブルに次の条件を追加します。
AND xte.application_id = xe.application_id --利用表分区表特性缩小范围
AND xte.application_id = 140 --利用表分区表缩小范围
再度クエリを実行したところ、効率が大幅に向上したことがわかりました。それでも、やや大量のデータ (数千レコード) の場合は数分かかりますが、少量のデータ (数百レコード) の場合は 1 分かかります。 24 個の論理コアを使用すると非常に長い時間がかかるため、最適化の余地があるはずです。
ビジネス分析と組み合わせる
このレポートを実行する際のセッション追跡を通じて、問題のある sqlid を特定し、無料の Oracle ツールである sqlhc を使用して、非常に単純なコマンド
sql> sqlhc T [sqlid]
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 99.98%)
------------------------------------------
- Consider accepting the recommended SQL profile.
execute dbms_sqltune.accept_sql_profile(task_name =>
'fpkqh87w1y36b_tuning_task', task_owner => 'SYS', replace =>
TRUE);
2- Index Finding (see explain plans section below)
--------------------------------------------------
The execution plan of this statement can be improved by creating one or more
indices.
Recommendation (estimated benefit: 98.65%)
------------------------------------------
- Consider running the Access Advisor to improve the physical schema design
or creating the recommended index.
create index XLA.IDX$$_A3EE0001 on XLA.XLA_TRANSACTION_ENTITIES("SOURCE_ID_
INT_1");
- Consider running the Access Advisor to improve the physical schema design
or creating the recommended index. If you choose to create the
recommended index, consider dropping the index "FA"."FA_BOOKS_N2" because
it is a prefix of the recommended index.
create index FA.IDX$$_A3EE0002 on FA.FA_BOOKS("TRANSACTION_HEADER_ID_OUT","
ASSET_ID");
- Consider running the Access Advisor to improve the physical schema design
or creating the recommended index.
create index FA.IDX$$_A3EE0003 on FA.FA_TRANSACTION_HEADERS("BOOK_TYPE_CODE
","TRANSACTION_TYPE_CODE","TRANSACTION_SUBTYPE");
- Consider running the Access Advisor to improve the physical schema design
or creating the recommended index.
create index FA.IDX$$_A3EE0004 on FA.FA_ADJUSTMENTS("TRANSACTION_HEADER_ID"
);
Rationale
---------
Creating the recommended indices significantly improves the execution plan
of this statement. However, it might be preferable to run "Access Advisor"
using a representative SQL workload as opposed to a single statement. This
will allow to get comprehensive index recommendations which takes into
account index maintenance overhead and additional space consumption.
最初の部分は、実行計画を書き直すことです。場合によっては、パフォーマンスが大幅に向上することがあります。それをシステムにフラッシュして試してみることができます。
2 番目の部分はインデックスのメンテナンスです。大きなテーブル XLA_TRANSACTION_ENTITIES にフィールド SOURCE_ID_INT_1 のインデックスを作成するという提案があることがわかりました。このフィールドは通常、さまざまなビジネス モジュールからのトランザクションの主キーですが、このテーブルは共通のサブキーです。テーブルは他のモジュールでも使用されるため、他のモジュールの更新効率に影響を与えることを恐れて、むやみにインデックスを追加しないでください。通常の複合インデックスという 2 つのインデックスがあるテーブルの既存のインデックスを利用できるかどうかを検討してください
。
(LEDGER_ID, ENTITY_CODE, NVL(SOURCE_ID_INT_1,(-99)), NVL(SOURCE_ID_INT_2,(-99)), NVL(SOURCE_ID_INT_3,(-99)), NVL(SOURCE_ID_INT_4,(-99)), NVL(SOURCE_ID_CHAR_1,' '), NVL(SOURCE_ID_CHAR_2,' '), NVL(SOURCE_ID_CHAR_3,' '), NVL(SOURCE_ID_CHAR_4,' '))
一意の複合インデックス:
ENTITY_ID, APPLICATION_ID
すでに一意のインデックスを使用しているため、結合インデックスを使用できるかどうかを検討してください。この SQL では大きなテーブル XLA_TRANSACTION_ENTITIES の SOURCE_ID_INT_1 フィールドを使用しましたが、LEDGER_ID と ENTITY_CODE の 2 つのフィールドは使用されていないため、このインデックスは使用されません。元の SQL 結果に影響を与えることなく SQL を書き換えることで、この SQL プレフィックスを使用できるかどうか ビジネス分析を通じて、LEDGER_ID が総勘定元帳セットの ID であり、FA モジュールを元に遡ると 2 つの部分に分割されていることがわかりました。補助元帳資産
トランザクションと資産減価償却、ENTITY_CODE に対応する 2 つの値は [TRANSACTIONS] と [DEPRECIATION] です。私たちのビジネスのこの部分には資産減価償却が含まれていないため、この大きなトランザクションの ENTITY_CODE フィールドの値を修正できます。 TRANSACTIONS としてテーブルを作成します。
同時に、資産台帳は、資産台帳の構成テーブル fa_book_controls を通じて総勘定元帳に関連付けることができ、この大きなテーブルの既存のインデックスを使用して、大きなテーブルの範囲スクリーニングを高速化できます。 、次の SQL に示すように:
--加入资产账簿配置表
fa_book_controls fbc
--加入如下关联条件
AND xte.ledger_id = fbc.set_of_books_id --利用xla_transaction_entities现有索引
AND fbc.book_type_code = h.book_type_code --利用xla_transaction_entities现有索引
AND xte.entity_code = 'TRANSACTIONS' --利用xla_transaction_entities现有索引
最適化されたSQL
最適化された SQL は次のとおりです。
SELECT a.asset_id,
to_char(h.transaction_date_entered, 'yyyy-mm-dd hh24:mi:ss'),
to_char(xe.transaction_date, 'yyyy-mm-dd'),
b.book_type_code,
a.asset_number,
a.description,
c.segment1,
c.segment2,
b.original_cost amount,
'增加' trans_type
FROM fa_transaction_headers h,
fa_additions_vl a,
fa_books b,
fa_categories c,
xla_transaction_entities xte,
xla_events xe,
fa_asset_invoices i,
fa_book_controls fbc --增加资产账簿以便同子分类账关联
WHERE a.asset_id = h.asset_id
AND b.asset_id = a.asset_id
AND c.category_id = a.asset_category_id
AND h.book_type_code = b.book_type_code
AND i.asset_id = a.asset_id
AND b.date_ineffective IS NULL
AND h.transaction_type_code = 'ADDITION'
AND h.transaction_header_id = nvl(xte.source_id_int_1, (-99))
AND xte.entity_id = xe.entity_id
/* 下面是新增的关联条件及原因 */
AND xte.application_id = xe.application_id --利用表分区表特性缩小范围
AND xte.application_id = 140 --利用表分区表缩小范围
AND xte.ledger_id = fbc.set_of_books_id --利用xla_transaction_entities现有索引
AND fbc.book_type_code = h.book_type_code --利用xla_transaction_entities现有索引
AND xte.entity_code = 'TRANSACTIONS' --利用xla_transaction_entities现有索引
このレポート SQL を書き換えて 1 つの資産台帳を実行し、1 か月のデータを数秒で表示できます。
分析する
上記の書き換えの一部は、2 つの非常に単純なアイデアに従っています。
- パーティション制限や固定ビジネス定数を使用するなど、データのクエリ範囲を可能な限り最小限に抑えます。
- 小さなテーブルを使用して大きなテーブルを駆動します。理想的には、小さなテーブルと大きなテーブルに関連付けられたフィールドにインデックスが付いています。2 つ目は、小さなテーブルにはインデックスがなくても、大きなテーブルにはインデックスがあるということです。
これら 2 つの原則は、Oracle データベースだけでなく、他のリレーショナル データベースにも当てはまります。