Question

En procédant comme suit, je peux déterminer si un indice bénéficiera de la compression et le nombre de colonnes doit être inclus dans la compression:

ANALYZE INDEX Owner.IndexName VALIDATE STRUCTURE OFFLINE;
SELECT Opt_Cmpr_PctSave, Opt_Cmpr_Count FROM Index_Stats; 

Le problème est que lorsque OFFLINE est changé pour ONLINE la vue Index_Stats ne soit pas peuplée. Est-il un moyen en ligne pour déterminer le bénéfice de la compression d'un index et / ou le nombre de colonnes qui produira une compression optimale?

Mise à jour:

http://jonathanlewis.wordpress.com/index-definitions/ indique que si Distinct_Keys de dba_indexes est « beaucoup plus petit » que num_rows alors l'index est un bon candidat pour la compression. Cela aide un peu, mais pas définitive et ne permet pas de déterminer le nombre de colonnes. Il ne donne quelques directives pour cela, mais rien qui peut être déterminé sans programatically tas de SQL dynamique.

Était-ce utile?

La solution

Le nombre optimal de colonnes pour compresser dépend :

  • Le nombre d'entrées qui adapteront dans chaque bloc (cela dépend du nombre de colonnes compressées car ils ne sont stockés qu'une fois par bloc)
  • Le nombre moyen d'entrées avec le même préfixe

Ces facteurs peuvent être estimés pour la table

Le but est de maximiser la taille du préfixe comprimé tout en minimisant le nombre de blocs nécessaires pour maintenir toutes les lignes avec le même préfixe.

Si l'on suppose que les données est uniforme au moins dans une certaine mesure, et sans tenir compte de la faible quantité de compression introduit en tête, vous pourriez essayer de mettre en œuvre cette approche comme ceci:

Fonctions auxiliaires:

create or replace function f_size( p_table_name in varchar, 
                                   p_column_name in varchar) 
                  return number as
  n number;
begin
  execute immediate 
    'select avg(vsize('||p_column_name||'))+1 from '||p_table_name into n;
  return n;
end;
/

create or replace function f_count( p_table_name in varchar, 
                                    p_column_names in varchar ) 
                  return integer as
  n integer;
begin
  execute immediate 'select count(*) '||
                    'from ( select '|| p_column_names || 
                           ' from '||p_table_name||' '||
                           'group by '||p_column_names||' )' 
          into n;
  return n;
end;
/

Test IOT:

create table t ( k1, k2, k3, k4, k5, val, 
                 constraint pk_t primary key(k1, k2, k3, k4, k5)) 
       organization index as
select mod(k,10)||'_____', 
       mod(k,20)||'_____', 
       mod(k,30)||'_____', 
       mod(k,50)||'_____', 
       k||'_____', 
       lpad(' ',100)
from (select level as k from dual connect by level<=1000);

query:

with utc as (select table_name, column_name, f_size(table_name, column_name) as column_size from user_tab_columns where table_name='T'),
     uic as (select table_name, column_name, column_position, column_size from user_ind_columns join utc using(table_name, column_name) where index_name='PK_T')
select z.*, (8192-prefix_size*prefixes_per_block)/remaining_size as rows_per_block
from( select z.*, greatest(1,8192/(prefix_size+rows_per_prefix*remaining_size)) as prefixes_per_block
      from( select z.*, total_count/distinct_count as rows_per_prefix
            from( select prefix_length, sum(column_size) as prefix_size, (select sum(column_size) from utc)-sum(column_size) as remaining_size, f_count(table_name, max(prefix_columns)) as distinct_count, 
                         (select count(*) from t) as total_count
                  from( select table_name, connect_by_root column_position as prefix_length, column_size, substr(sys_connect_by_path(column_name, ','),2) as prefix_columns
                        from uic
                        connect by column_position=(prior column_position-1) )
                  group by table_name, prefix_length ) z ) z ) z
order by 1;

résultat:

PREFIX_LENGTH          PREFIX_SIZE            REMAINING_SIZE         DISTINCT_COUNT         TOTAL_COUNT            ROWS_PER_PREFIX        PREFIXES_PER_BLOCK     ROWS_PER_BLOCK         
---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- 
1                      7                      132.854                10                     1000                   100                    1                      61.608 
2                      14.5                   125.354                20                     1000                   50                     1.304                  65.200 
3                      22.161                 117.693                60                     1000                   16.666                 4.129                  68.827 
4                      29.961                 109.893                300                    1000                   3.333                  20.672                 68.909 
5                      38.854                 101                    1000                   1000                   1                      58.575                 58.575 

vérifier:

analyze index pk_t validate structure;
select opt_cmpr_pctsave, opt_cmpr_count from index_stats;

OPT_CMPR_PCTSAVE       OPT_CMPR_COUNT         
---------------------- ---------------------- 
13                     3                      

Le chèque ci-dessus correspond à peu près à la longueur du préfixe avec le rows_per_block maximum dans le calcul - mais je vous suggère de vérifier mon travail avec soin pour vous-même avant de lui faire confiance:)

Je suppose la table est si grand que vous ne pouvez pas prendre une copie et essayer différentes longueurs de préfixe. Une autre approche serait de le faire que sur un échantillon des données - l'échantillon doit être choisi comme une sélection aléatoire des préfixes pour un candidat de compression donné (plutôt qu'une simple sélection aléatoire de lignes)

Autres conseils

Ceci est la question:

http://download.oracle. com / docs / cd / E11882_01 / server.112 / e17118 / statements_4005.htm # SQLRF53681

Quand il se fait en ligne, pas de statistiques sont recueillies, de sorte que vous ne recevez pas votre réponse.

Je crains que vous allez devoir le faire au cours d'une période de calme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top