Déterminer les candidats en ligne Index Compression
-
16-10-2019 - |
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.
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:
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.