Optimisation des performances SQL : une étude de cas sur l'optimisation des rapports d'actifs EBS

Le module d'actif dispose d'un rapport personnalisé, qui consiste à interroger les informations du module d'actif et les informations comptables via la table associée FA_ et le sous-livre XLA. Avant l'optimisation, il faut une heure pour exécuter les données d'un ensemble de comptes d'actif unique pour un seul mois.Après l'optimisation SQL et la réécriture, il s'exécute en une seconde environ. Cet article utilise des moyens relativement simples pour analyser étape par étape comment optimiser

idéologie directrice fondamentale

  1. Affinez autant que possible la plage de données de la requête
  2. Utiliser de petites tables pour piloter de grandes tables

Performances de positionnement SQL

Il s'agit d'un paquet pkg volumineux, qui peut impliquer des centaines ou des milliers de lignes de code. Comment localiser rapidement quel morceau de code est le coupable et entraîner une baisse de la vitesse du rapport. Vous devez utiliser un outil d'analyse DBMS_HPROF fourni avec Oracle. Pour une introduction et une utilisation, voir Cet article
Optimisation des performances ORACLE - DBMS_HPROF

SQL avant optimisation

Après quelques commandes simples à l'étape précédente, nous avons positionné le sql de performance. Il s'agit d'un UNION SQL avec une structure très similaire. Ici, nous ne prenons qu'une partie à titre d'exemple.

--该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

Idées de traitement

Analyse des données (non combinée avec les affaires)

Supposons que nous ne connaissions pas la structure et l'activité des tables EBS, et analysons-les uniquement d'un point de vue technique.
Ce SQL n'est pas compliqué. Il n'y a que des tables 7. Selon l'échelle des données statistiques, l'échelle des données des tables associées commençant par FA_ est d'environ des dizaines de milliers, qui sont de petites tables. Les tables commençant par XLA_ sont de millions à des dizaines de millions, qui sont de grandes tables.
Après avoir vérifié l'index de la table associée (ici, nous nous concentrons sur l'index et la structure de la grande table), nous avons constaté que la table associée à XLA_ est une table de partition, qui est partitionnée par le champ application_id, mais la restriction de partition n'est pas utilisée dans le au-dessus de SQL.Après la requête sql ci-dessus, j'ai trouvé que l'application_id pris par ce sql est exactement le même, les deux sont 140. J'ai appris des consultants techniques EBS qui ont un ou deux ans d'expérience (ici, nous supposons que nous ne comprenons pas EBS business et table structure du tout, et avoir une petite expérience de la technologie EBS Tous les consultants savent que ce champ est le champ ID du module métier) En fait, ce sql est le sql de la requête conjointe entre le module asset et le sous-livre. La table commençant par xla_ contient le champ de module métier application_id. L'application_id correspondant au module d'actif est 140 et il n'y a pas d'autre valeur.
Ensuite, nous pouvons tirer parti des fonctionnalités de la table de partition, ajouter des restrictions de partition et ajouter les conditions suivantes à la grande table

AND xte.application_id = xe.application_id --利用表分区表特性缩小范围
AND xte.application_id = 140 --利用表分区表缩小范围

Après avoir interrogé à nouveau, j'ai constaté que l'efficacité s'était beaucoup améliorée.Cela prend encore quelques minutes pour une quantité de données légèrement plus importante (des milliers d'enregistrements), et une minute pour une quantité de données plus petite (des centaines d'enregistrements). avec 24 cœurs logiques prendra tellement de temps, et il devrait y avoir de la place pour l'optimisation.

Combiné à l'analyse commerciale

Grâce au suivi de session lors de l'exécution de ce rapport, nous localisons le sqlid problématique, puis utilisons sqlhc, un outil Oracle gratuit, pour obtenir un rapport d'analyse complet avec une commande très simple
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.

La première partie consiste à réécrire le plan d'exécution. Dans certains cas, les performances peuvent être grandement améliorées. Vous pouvez le flasher dans le système pour un essai.
La deuxième partie est la maintenance de l'index. Nous avons remarqué qu'il est suggéré de créer un index du champ SOURCE_ID_INT_1 sur la grande table XLA_TRANSACTION_ENTITIES. Ce champ est généralement la clé primaire des transactions de divers modules métier, mais cette table est une sous- Les tables sont également utilisées par d'autres modules, alors n'osez pas ajouter des index à la va-vite, de peur d'affecter l'efficacité de la mise à jour des autres modules. Déterminez si vous pouvez tirer parti des index existants sur la table,
qui comporte deux index, un index composite standard :

(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,' '))

Un indice composite unique :

ENTITY_ID, APPLICATION_ID

Nous avons déjà utilisé l'index unique, donc considérons si nous pouvons utiliser l'index combiné. Nous avons utilisé le champ SOURCE_ID_INT_1 sur la grande table XLA_TRANSACTION_ENTITIES pour ce sql, mais les deux champs LEDGER_ID et ENTITY_CODE ne sont pas utilisés, donc cet index n'est pas utilisé, s'il est possible d'utiliser ce préfixe sql en réécrivant sql sans affecter les résultats sql d'origine.Grâce à l'analyse commerciale, nous savons que LEDGER_ID est l'ID de l'ensemble de grand livre général et que le module FA est divisé en deux parties lors de la remontée au transaction d'actif de sous-livre
Et amortissement d'actif, les deux valeurs correspondant à ENTITY_CODE sont [TRANSACTIONS] et [DEPRECIATION], cette partie de notre activité n'implique pas d'amortissement d'actif, nous pouvons donc fixer la valeur du champ ENTITY_CODE de ce grand table comme TRANSACTIONS.
Dans le même temps, le livre de comptes d'actifs peut être associé au livre de comptes du grand livre général via la table de configuration fa_book_controls du livre de comptes d'actifs, puis nous pouvons utiliser l'index existant de cette grande table pour accélérer le filtrage de plage de la grande table , comme indiqué dans le sql suivant :

--加入资产账簿配置表 
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 optimisé

Le sql optimisé est le suivant :

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现有索引

Ce rapport sql peut être réécrit pour exécuter un seul livre de comptes d'actifs, et les données d'un seul mois peuvent être affichées en quelques secondes.

analyser

Une partie de la réécriture ci-dessus consiste à suivre deux idées très simples

  1. Minimisez autant que possible la plage de requêtes de données, par exemple en utilisant des restrictions de partition et des constantes métier fixes
  2. Utilisez de petites tables pour piloter de grandes tables. Idéalement, les champs associés aux petites tables et aux grandes tables ont des index. Deuxièmement, les petites tables peuvent ne pas avoir d'index, et les grandes tables ont des index.

Ces deux principes ne s'appliquent pas seulement aux bases de données Oracle, mais également aux autres bases de données relationnelles.

Je suppose que tu aimes

Origine blog.csdn.net/x6_9x/article/details/118682125
conseillé
Classement