Expliquer le Plan des Coûts vs Temps d'Exécution
Avant, j'ai trouvé le "Coût" dans le plan d'exécution pour être un bon indicateur de rapport de temps d'exécution. Pourquoi cette affaire est-elle différente? Suis-je un imbécile pour penser le plan d'exécution a une pertinence? Que puis-je essayer d'améliorer v_test performance?
Merci.
De l'utilisation d'Oracle 10g j'ai une requête simple vue définie ci-dessous
create or replace view v_test as
select distinct u.bo_id as bo_id, upper(trim(d.dept_id)) as dept_id
from
cust_bo_users u
join cust_bo_roles r on u.role_name=r.role_name
join cust_dept_roll_up_tbl d on
(r.region is null or trim(r.region)=trim(d.chrgback_reg)) and
(r.prod_id is null or trim(r.prod_id)=trim(d.prod_id)) and
(r.div_id is null or trim(r.div_id)=trim(d.div_id )) and
(r.clus_id is null or trim(r.clus_id )=trim( d.clus_id)) and
(r.prod_ln_id is null or trim(r.prod_ln_id)=trim(d.prod_ln_id)) and
(r.dept_id is null or trim(r.dept_id)=trim(d.dept_id))
défini pour remplacer la vue suivante
create or replace view v_bo_secured_detail
select distinct Q.BO_ID, Q.DEPT_ID
from (select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'REGION' and
trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'RG_PROD' and
trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and
trim(R.PROD_ID) = UPPER(trim(D.PROD_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'PROD' and
trim(R.PROD_ID) = UPPER(trim(D.PROD_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'DIV' and
trim(R.DIV_ID) = UPPER(trim(D.DIV_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'RG_DIV' and
trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and
trim(R.DIV_ID) = UPPER(trim(D.DIV_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'CLUS' and
trim(R.CLUS_ID) = UPPER(trim(D.CLUS_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'RG_CLUS' and
trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and
trim(R.CLUS_ID) = UPPER(trim(D.CLUS_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(D.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R, CUST_DEPT_ROLL_UP_TBL D
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'PROD_LN' and
trim(R.PROD_LN_ID) = UPPER(trim(D.PROD_LN_ID))
union all
select U.BO_ID BO_ID, UPPER(trim(R.DEPT_ID)) DEPT_ID
from CUST_BO_USERS U, CUST_BO_ROLES R
where U.ROLE_NAME = R.ROLE_NAME and
R.ROLE_LEVEL = 'DEPT') Q
avec l'objectif de la suppression de la dépendance sur la ROLE_LEVEL colonne.
Le plan d'exécution pour v_test est significativement plus faible que v_bo_secured_detail pour de simples
select * from <view> where bo_id='value'
requêtes. Et est significativement plus faible lorsque utilisé dans un monde réel de la requête
select CT_REPORT.RPT_KEY,
CT_REPORT_ENTRY.RPE_KEY,
CT_REPORT_ENTRY.CUSTOM16,
Exp_Sub_Type.value,
min(CT_REPORT_PAYMENT_CONF.PAY_DATE),
CT_REPORT.PAID_DATE
from CT_REPORT,
<VIEW> SD,
CT_REPORT_ENTRY,
CT_LIST_ITEM_LANG Exp_Sub_Type,
CT_REPORT_PAYMENT_CONF,
CT_STATUS_LANG Payment_Status
where (CT_REPORT_ENTRY.RPT_KEY = CT_REPORT.RPT_KEY) and
(Payment_Status.STAT_KEY = CT_REPORT.PAY_KEY) and
(Exp_Sub_Type.LI_KEY = CT_REPORT_ENTRY.CUSTOM9 and Exp_Sub_Type.LANG_CODE = 'en') and
(CT_REPORT.RPT_KEY = CT_REPORT_PAYMENT_CONF.RPT_KEY) and
(SD.BO_ID = 'JZHU9') and
(SD.DEPT_ID = UPPER(CT_REPORT_ENTRY.CUSTOM5)) and
(Payment_Status.name = 'Payment Confirmed' and (Payment_Status.LANG_CODE = 'en') and
CT_REPORT.PAID_DATE > to_date('01/01/2008', 'mm/dd/yyyy') and Exp_Sub_Type.value != 'Korea')
group by CT_REPORT.RPT_KEY,
CT_REPORT_ENTRY.RPE_KEY,
CT_REPORT_ENTRY.CUSTOM16,
Exp_Sub_Type.value,
CT_REPORT.PAID_DATE
Les temps d'exécution sont très différentes. Le v_test vue de 15 heures, et le v_bo_secured_detail de prendre quelques secondes.
Merci à vous tous qui ont répondu
C'est un souvenir pour moi. Les endroits où la théorie et les mathématiques des expressions qui répond à la réalité de matériel en fonction de l'exécution. Ouch.
OriginalL'auteur Samuel Renkert | 2008-09-19
Vous devez vous connecter pour publier un commentaire.
Comme la documentation d'Oracle dit, le coût est le coût estimé relative à un plan d'exécution. Lorsque vous ajustez la requête, le plan de l'exécution, les coûts sont calculés par rapport à peut changer. Parfois de façon spectaculaire.
Le problème avec v_test de la performance d'Oracle pouvez penser d'aucune manière de l'exécuter d'autres que l'exécution d'une boucle imbriquée, pour chaque cust_bo_roles, balayer l'ensemble des cust_dept_roll_up_tbl pour trouver une correspondance. Si la table sont de taille n et m, il faut n*m temps, qui est trop lent pour les grandes tables. En revanche v_bo_secured_detail est mis en place de sorte que c'est une série de requêtes, chaque de ce qui peut être fait par le biais d'un autre mécanisme. (Oracle a un certain nombre, y compris à l'aide d'un indice, la construction d'un hachage à la volée, ou de trier les ensembles de données et de leur fusion. Ces opérations sont toutes en O(n*log(n)) ou mieux). Une petite série de requêtes rapides est rapide.
Aussi pénible qu'elle est, si vous voulez que cette requête pour être rapide, alors vous devez casser comme la précédente requête n'.
OriginalL'auteur user11318
Un plan d'exécution est de la théorie, le temps d'exécution est la réalité.
Le plan vous montre comment le moteur va sur l'exécution de votre requête, mais certaines étapes peuvent causer une quantité excessive de travail pour résoudre la requête. L'utilisation de "x est nul ou x = y" sent mauvais. Si r et d sont de grandes tables, vous pourriez avoir une sorte d'explosion combinatoire de vous taper et de la demande des cycles à l'infini à travers de grandes listes de blocs sur le disque. J'imagine que vous avez vu beaucoup d'I/O au cours de l'exécution.
D'autre part, l'réunies sélectionne sont courts et doux, et donc probablement la réutilisation de beaucoup de blocs de disque qui sont encore traîner à partir de l'sélectionne, et/ou vous avez un certain degré de parallélisme bénéficiant de lit sur le même disque des blocs.
Également à l'aide de trim() et supérieur (de) partout, l'air un peu suspect. Si vos données sont donc impur, il pourrait être utile à l'exécution de certains périodiques faire le ménage de temps en temps, de sorte que vous pouvez dire "x = y" et savent que cela fonctionne.
mise à jour: vous avez demandé des conseils pour améliorer v_test. Nettoyer vos données de sorte que trim() et supérieur (de) sont unnecessay. Ils peuvent empêcher les indices d'être utilisé (bien que ce serait affectant l'réunies sélectionnez la version).
Si vous ne pouvez pas vous débarrasser de "x est nul ou x = y, alors y = nvl(x,'n'existe pas') ont de meilleures caractéristiques (en supposant que "n'existe pas" est un "ne peut pas se produire" valeur de l'id).
OriginalL'auteur dland
Un aspect de faible coût, un temps d'exécution est que lorsque vous êtes à la recherche à de grands ensembles de données, il est souvent plus efficace sur l'ensemble de la à faire des choses en vrac, tandis que si vous voulez un résultat rapide, il est plus efficace de faire aussi peu de travail que possible pour obtenir le premier enregistrement. La répétitivité de faire de petites opérations qui donnent l'apparence d'une réponse rapide ne sera pas susceptible de donner un bon résultat lorsque vous travaillez sur de grands ensembles.
Plusieurs fois, lorsque vous voulez un résultat rapide, la USE_NL optimiseur indicateur de l'aide.
Aussi, dans votre test de vue, c'est en comptant sur EST NULLE... EST NULL ne peut pas utiliser un index ne peut à l'aide d'une fonction, telle que la garniture sur la " table de côté paramètre.
OriginalL'auteur Greg Ogle
Avez-vous recueilli l'optimiseur de statistiques sur toutes les tables sous-jacentes? Sans eux, l'optimiseur estimations peuvent être très en décalage avec la réalité.
OriginalL'auteur Tony Andrews
Quand vous dites que le "plan de requête est plus faible", voulez-vous dire qu'il est plus court, ou que les estimations de coûts sont plus bas? Un problème évident avec le remplacement de votre point de vue est que la jointure avec cust_dept_roll_up_tbl utilise presque exclusivement des unindexable critères (le "is null" tests peuvent être satisfaits par un index, mais ceux impliquant l'appel de la garniture sur chaque argument peut pas être), de sorte que le planificateur doit faire au moins un, et probablement plusieurs analyses séquentielles de la table pour satisfaire à la requête.
Je ne suis pas sûr si Oracle a cette limitation, mais beaucoup de DBs ne peut le faire une seule analyse d'index par table, de sorte que même si vous nettoyez vos conditions de jointure à être indexées, il peut être en mesure de satisfaire à une seule condition, avec un indice de numérisation et d'avoir à utiliser des analyses séquentielles pour le reste.
OriginalL'auteur Nick Johnson
Pour des précisions à propos d'un coût un peu.
Dans Oracle 9/10g, en simplifiant un peu, le coût est déterminé par la formule:
Coût = (SrCount * SrTime + MbrCount * MbrTime + CpuCyclesCount * CpuCycleTime) /SrTime
Où SrCount - nombre total de bloc unique, lit fait, SrTime - temps moyen d'un seul bloc de lecture selon réunis système de statistiques, MbrCount et MbrTime, le même pour multiblock lire également (ceux utiliser lors de la pleine analyses de tables et d'index rapide des scans complets), Cpu mesures sont explicites..et le tout divisé par un seul bloc de temps de lecture.
OriginalL'auteur Zorkus