tag:blogger.com,1999:blog-456686155150137588.post7184658882129898618..comments2023-11-08T23:42:52.114+01:00Comments on Le blog Oracle d'Ahmed AANGOUR: Les statistiques étendues (2)Ahmed AANGOURhttp://www.blogger.com/profile/03378785645074450748noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-456686155150137588.post-75469839058699377212013-12-27T16:42:48.090+01:002013-12-27T16:42:48.090+01:00Ahmed
Tu as raison en ce qui concerne le Starts l...Ahmed<br /><br />Tu as raison en ce qui concerne le Starts lorsqu'il s'agit d'une opération PARTITION RANGE xxxx. Voici un exemple<br /><br />SQL> select count(1) from partitioned_tab;<br /><br /> COUNT(1)<br />----------<br /> 1493<br /><br />SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));<br /><br />---------------------------------------------------------------------------<br />| Id | Operation | Name | Starts | E-Rows | A-Rows |<br />---------------------------------------------------------------------------<br />| 0 | SELECT STATEMENT | | 1 | | 1 |<br />| 1 | SORT AGGREGATE | | 1 | 1 | 1 |<br />| 2 | PARTITION RANGE ALL| | 1 | 1493 | 1493 |<br />| 3 | TABLE ACCESS FULL | PARTITIONED_TAB | 1493 | 1493 | 1493 |<br />---------------------------------------------------------------------------<br /><br />Je vois aussi que dans ta deuxième requête, si je m'abuse, que tu peux la ré-ecrire (sans aucune garantie car je ne l'ai pas essayée et je ne la connais pas ) en sortant la somme du distinct, faire le distinct sur les colonnes et puis après appliquer la somme. Quelque chose comme ça <br /><br />SELECT <br /> x.Date_arrete<br /> ,x.Num_contrat<br /> SUM (<br /> DECODE (x.id_col1,<br /> '00698', 12 * rttc,<br /> '77009', 12 * rttc,<br /> '90074', 12 * rttc, 4 * rttc)<br /> )<br />FROM<br /> (<br /> select <br /> DISTINCT<br /> FLC_DT_FIN_ECH_FLUX Date_arrete,<br /> ASS_NUM_CONTR_COLLECT_CNP Num_contrat,<br /> ASS_NUM_CONTRACTANT Id_coll,<br /> ADH_SOMME_MVT_RELATIFS_TTC rttc<br />FROM odd_flux_cid a<br /> , odd_assure b<br /> , odd_info_adhesion d<br />where a.num_integration in (8118,8112,8069,8186,8148,8119,8094,8070,8187,8149,8120,8095,8071,8121,8096,8072,8188,8150,8122,8097,8073,8189,8151,8123,8098,8074,8190,8152,8125,8099,8075,8191,8153,8127,<br />8100,8192,8154,8129,8101,8077,8193,8155,8130,8102,8078,8194,8156,8131,8103,8079,8195,8158,8132,8104,8080,8197,8159,8133,8105,8081,8162,8134,8106,8082,8198,8163,8135,8107,8083,8200,8164,8136,8108,8084,<br />8137,8110,8085,8165,8138,8109,8086,8202,8166,8139,8111,8087)<br /> AND b.num_integration = d.num_integration<br /> AND ASS_ID_FLUX = ADH_ID_FLUX<br /> AND ASS_NUM_CCOLTE = ADH_NUM_CCOLTE<br /> AND ASS_NUM_REF_ASS = ADH_NUM_REF_ASS<br /> AND a.num_integration = b.num_integration<br /> AND ASS_ID_FLUX = flc_id_flux<br /> AND ASS_ID_DELEGATAIRE = flc_id_delegataire<br /> ) x<br />GROUP BY FLC_DT_FIN_ECH_FLUX<br /> , ASS_NUM_CONTR_COLLECT_CNP<br /> , ASS_NUM_CONTRACTANT;<br /><br />Bien à toi<br /><br />Mohamed Hourihttps://www.blogger.com/profile/11687776847553675567noreply@blogger.comtag:blogger.com,1999:blog-456686155150137588.post-1812826986919351142013-12-27T12:05:42.521+01:002013-12-27T12:05:42.521+01:00Hello Mohamed,
C'est toujours un plaisir de li...Hello Mohamed,<br />C'est toujours un plaisir de lire un commentaire de ta part.<br />Mon client n'a pas partitionné sur l'expression SUBSTR mais sur un autre champ qui correspond en fait aux 3 premiers caractères du champ RBQ_NUM_CONTR. Ce champ est bien utilisé dans la plupart des requêtes mais il existe certaines requêtes (qui doivent surement dater d'avant l'existence de la colonne sur laquelle est basée le partitioning ) qui utilisent l'expression (substr(RBQ_NUM_CONTR,1,3)) au lieu de se baser sur le critère de partitioning.<br /><br />Concernant ta remarque sur l'estimation de 18M après le calcul de stats étendues sur l'expression, je me suis basé sur l'opération PARTITION LIST ALL qui a un START à 1 et un E-ROWS et A-ROWS tous les 2 à 18M. Alors c'est vrai que l'opération enfant TABLE ACCESS FULL a un START de 227 (ce qui correspond par ailleurs au nombre de partitions de la table) et que normalement A-ROWS doit être égal à E-ROWS*STARTS mais je ne suis pas sûr que ça s'applique pour les scans de partitions puisque chaque opération TABLE ACCESS FULL correspond en fait à un scan de partition et que chaque partition peut avoir un E-ROWS différent.<br /><br />Enfin concernant le PARTITION RANGE AND, je te rassure moi non plus je ne l'avais jamais vu. J'avais d'abord cherché dans le livre de Christian Antognini mais je n'ai rien trouvé. Je pense qu'il s'agit d'une opération de DYNAMIC PRUNING qui apparaît lorsqu'on joint plusieurs tables selon le critère de partitioning mais que le critère n'est précisé réellement que pour une seule table. Je vais essayer de faire un testcase pour confirmer cela mais c'est vrai que c'est bizarre que ça ne soit pas documenté.Ahmed AANGOURhttps://www.blogger.com/profile/03378785645074450748noreply@blogger.comtag:blogger.com,1999:blog-456686155150137588.post-17295287237417431912013-12-27T11:01:29.157+01:002013-12-27T11:01:29.157+01:00Salam Ahmed,
Excellent article. J’ai pris du plais...Salam Ahmed,<br />Excellent article. J’ai pris du plaisir à le lire. N’hésites pas à partager ce genre de situation. Depuis que j’ai assisté à un webinar de Jonathan Lewis sur les statistiques j’ai compris l’importance cruciale des statistiques étendues lorsqu’il s’agit d’avoir une bonne estimation et donc un plan d’exécution optimal.<br />Si je reviens à ton article, quelle drôle d’idée a eu ce client de partitionner sur une partie du contenu d’une colonne en l’occurrence ici les trois premières positions. Ils doivent faire attention quand ils devront indexer ce genre de combinaison et en même temps utiliser le cursor_sharing a FORCE (voir mon commentaire ici http://jonathanlewis.wordpress.com/2013/09/27/virtual-stats/#comments)<br />J’ai entamé une série d’article sur le partition pruning et ce genre de partitionnement me donne une autre idée d’investigation.<br />Donc, créer des statistiques étendues reviens en fait à créer une colonne virtuelle. Je pense qu’il serait peut être plus intéressant dans votre cas de créer une colonne virtuelle (substr(RBQ_NUM_CONTR,1,3)) et partitionner par cette colonne. <br />Pour le premier cas exposé, après le calcul des statistiques étendues, tu dis que l’estimation est devenue bonne car E-Rows=A-Rows=18M. Mais on voit bien que l’opération a été exécutée 227 fois (Starts=227). Il faudrait comparer Start*E-Rows avec A-Rows. Mais bon ici, les chiffres sont tellement grands que des exceptions peuvent avoir lieu.<br /><br />Quant au second cas, je suis intrigué par l’opération PARTITION RANGE AND. Je ne l’ai jamais croisée. Une petite recherche sur Google n’a rien donné. Peux-tu m’en toucher quelques mots.<br />En suivant ton explication et en regardant le deuxième plan, je n’arrive pas à la même lecture du plan que tu as décrite ici. <br /><br />Néanmoins, je trouve cet article très instructif et ouvrant plusieurs pistes d’investigation.<br /><br />Bien à toi<br />Mohamed Houri<br />www.hourim.wordpress.com<br />Mohamed Hourihttps://www.blogger.com/profile/11687776847553675567noreply@blogger.com