2017-06-09 3 views
0

Oracle SQL qui doit être accordée:Oracle - que peut-on faire pour supprimer Full Table Scan/Table Access Full?

SELECT mcei.mcei_sid 
FROM MA_CE mc 
JOIN MA_CE_EN mce 
ON mc.mc_id=mce.mc_cd 
JOIN MA_CE_EN_IN mcei 
ON mce.mce_sid    =mcei.mce_sid 
WHERE mc.active_flag   = 'Y' 
AND mce.active_flag   = 'Y' 
AND Mcei.Latest_Full_Run_Flag = 'Y' 
AND Mcei.Engine_Type_Cg_Sid = GE_CG_SI_FR_C_SN ('MEI_ENGTYPE','COB') 
AND Mcei.Mcei_State_Cg_Sid = GE_CG_SI_FR_C_SN ('MCEI_STATE','COMPLETED') 
AND Mc.Mc_Id   = NVL(6,Mc.Mc_Id) 
AND mcei.business_dt = NVL(NULL -- this is a parameter which could be NULL or a Date  
    , 
    (SELECT mcei.business_dt 
    FROM MA_CE_EN e 
    WHERE e.current_cob_mei_sid =mcei.mcei_sid 
    AND e.active_flag   ='Y' 
    AND mcei.Latest_Full_Run_Flag='Y' 
    AND e.mce_sid    =mce.mce_sid 
)); 

Expliquer le plan:

---------------------------------------------------------------------------------------------------------------- 
| Id | Operation      | Name       | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |        |  1 | 40 | 825 (2)| 00:00:10 | 
|* 1 | FILTER      |        |  |  |   |   | 
|* 2 | HASH JOIN     |        | 376 | 15040 | 636 (3)| 00:00:08 | 
| 3 | NESTED LOOPS    |        |  1 | 14 |  4 (0)| 00:00:01 | 
|* 4 |  TABLE ACCESS BY INDEX ROWID| MA_CE       |  1 |  5 |  1 (0)| 00:00:01 | 
|* 5 |  INDEX UNIQUE SCAN   | IPK_MA_CE      |  1 |  |  0 (0)| 00:00:01 | 
|* 6 |  TABLE ACCESS FULL   | MA_CE_EN      |  1 |  9 |  3 (0)| 00:00:01 | 
|* 7 | TABLE ACCESS FULL   | MA_CE_EN_IN     | 4817 | 122K| 632 (3)| 00:00:08 | 
|* 8 | FILTER      |        |  |  |   |   | 
|* 9 | TABLE ACCESS BY INDEX ROWID | MA_CE_EN      |  1 | 11 |  1 (0)| 00:00:01 | 
|* 10 |  INDEX UNIQUE SCAN   | IPK_MCENG      |  1 |  |  0 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------------------------- 

prédicats information (identifié par id opération):

--------------------------------------------------- 

    1 - filter("MCEI"."BUSINESS_DT"= (SELECT :B1 FROM "MA_CE_EN" "E" WHERE :B2='Y' AND 
       "E"."MCE_SID"=:B3 AND "E"."CURRENT_COB_MEI_SID"=:B4 AND "E"."ACTIVE_FLAG"='Y')) 
    2 - access("MCE"."MCE_SID"="MCEI"."MCE_SID") 
    4 - filter("MC"."ACTIVE_FLAG"='Y') 
    5 - access("MC"."MC_ID"=6) 
    6 - filter("MCE"."ACTIVE_FLAG"='Y' AND "MC"."MC_ID"="MCE"."MC_CD") 
    7 - filter("MCEI"."LATEST_FULL_RUN_FLAG"='Y' AND 
       "MCEI"."MCEI_STATE_CG_SID"="GE_CG_SI_FR_C_SN"('MCEI_STATE','COMPLETED') AND 
       "MCEI"."ENGINE_TYPE_CG_SID"="GE_CG_SI_FR_C_SN"('MEI_ENGTYPE','COB')) 
    8 - filter(:B1='Y') 
    9 - filter("E"."CURRENT_COB_MEI_SID"=:B1 AND "E"."ACTIVE_FLAG"='Y') 
    10 - access("E"."MCE_SID"=:B1) 

--------------------------------------------------- 

Nombre de lignes dans la 3 tables utilisées dans la requête:

ma_ce - 10 
    ma_ce_en - 10 
    ma_ce_en_in - 160000 

(ma_ce_en_in table est coupable. Clé primaire sur les colonnes MCEI_SID et MCEI_SID_SEQ. Aucun autre index sur cette table)

Question 1 -. Je veux régler la requête, donc je ne veux pas complète Table de numérisation (ou table Full Access) sur ma_ce_en_in car cela est la seule grande table. Que peut-on faire pour supprimer l'analyse de table complète de cette table?

Question 2 - La requête ci-dessus est présente dans une fonction, comment trouver combien de fois la fonction s'exécute dans une semaine?

+0

Je ne suis pas très sûr de ce qu'est FTS? –

+0

L'analyse complète de la table OU l'accès à la table est complet. Edité ma question aussi. –

+0

Apparemment, Oracle est complètement sous-estimer le nombre de lignes dans 'ma_ce_en_in'. Vos statistiques sont-elles à jour? –

Répondre

0

Dans l'un des commentaires, en dessous du message (au lieu de IN THE POST où il devrait être), vous indiquez que vous avez un index sur LATEST_FULL_RUN_FLAG, MCEI_STATE_CG_SID et ENGINE_TYPE_CG_SID.

Combien de lignes le flag a-t-il défini sur 'Y'? (Vous pouvez exécuter une requête simple pour le savoir.) Si la réponse est "la moitié des lignes" ou même "15% des lignes", l'optimiseur choisira probablement de ne pas utiliser l'index. (Si seulement 1% des lignes avaient l'indicateur 'Y', l'index devrait être utilisé.)

Si tel est le cas, STATE_CG_SID ou ENGINE_TYPE_CG_SID sont-ils plus sélectifs? Par exemple, chaque valeur possible apparaît dans pas plus de 1% des lignes? Si c'est le cas, vous devez mettre le plus sélectif des colonnes FIRST dans l'index à plusieurs colonnes; La seule façon dont l'optimiseur peut utiliser l'index est si la valeur de la première colonne de l'index est très sélective. Sinon, vous finirez avec un scan complet de la table.

+0

merci à tous et @mathguy –

0

Question 2 - La requête ci-dessus est présente dans une fonction, comment trouver combien de fois la fonction s'exécute dans une semaine?

Réponse - Vous ne pouvez pas trouver le numéro. des fois qu'une fonction a été exécutée. Mais vous pouvez trouver combien de fois son sql a été exécuté.

a) Pour trouver le numéro. d'exécution, vous pouvez vérifier AWR mais il pourrait être possible que votre sql n'est pas ramassé par l'awr. Vous pouvez exécuter ci-dessous pour obtenir les statistiques de tout sql dans awr.

begin 
    dbms_workload_repository.modify_snapshot_settings (topnsql=>'MAXIMUM'); 
end; 

b) Toutefois, vous ne pouvez pas être autorisé à exécuter le code ci-dessus en prod. Donc, la prochaine option est de vérifier les vues oracle.

  1. Trouvez la SQL_ID de son texte

    exécutions sélectionner, v * de v $ sql v où sql_text comme '% select * from ABCtable%'; -. 90771ja3rt3rw

  2. select executions_delta-- "Executions" from dba_hist_sqlstat t, dba_hist_snapshot s where t.snap_id = s.snap_id and t.dbid = s.dbid and t.instance_number = s.instance_number and sql_id='90771ja3rt3rw' -- and to_char(BEGIN_INTERVAL_TIME, 'yyyy-mm-dd') = '2017-05-15' ;