以下を実行することで、インデックスが圧縮から利益を得るかどうか、および圧縮に含める列の数を決定できます。
ANALYZE INDEX Owner.IndexName VALIDATE STRUCTURE OFFLINE;
SELECT Opt_Cmpr_PctSave, Opt_Cmpr_Count FROM Index_Stats;
問題は、OFFLINE
がONLINE
に変更されると、Index_Statsビューにデータが入力されないことです。インデックスを圧縮するメリットや最適な圧縮を生成する列数をオンラインで決定する方法はありますか?
更新:
http://jonathanlewis.wordpress.com/index-definitions/ は、DBA_IndexesからのDistinct_Keysがnum_rowsよりも「はるかに小さい」場合、インデックスが圧縮に適していることを示します。これは一部には役立ちますが、決定的なものではなく、列数の決定には役立ちません。彼はそのためのいくつかのガイドラインを示していますが、動的SQLの束がなければプログラムで決定できるものは何もありません。
圧縮する列の最適数 依存する :
これらの要素は、テーブルに対して推定できます
目的は、同じプレフィックスを持つすべての行を保持するために必要なブロック数を最小限に抑えながら、圧縮されたプレフィックスのサイズを最大化することです。
データが少なくともある程度均一であると仮定し、導入される少量のオーバーヘッド圧縮を無視すると、次のようにこのアプローチを実装することができます。
ヘルパー関数:
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;
/
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);
クエリ:
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;
結果:
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
小切手:
analyze index pk_t validate structure;
select opt_cmpr_pctsave, opt_cmpr_count from index_stats;
OPT_CMPR_PCTSAVE OPT_CMPR_COUNT
---------------------- ----------------------
13 3
上記のチェックは、最大のrows_per_block
計算中ですが、信頼する前に自分の作業を注意深く確認することをお勧めします:)
テーブルが非常に大きいため、コピーを取ってさまざまな接頭辞の長さを試すことができないと想定しています。別のアプローチは、データのサンプルに対してそれを行うことです-サンプルは、(行のランダムな選択ではなく)所定の圧縮候補のプレフィックスのランダムな選択として選択する必要があります
これは問題です:
http://download.Oracle.com/docs/cd/E11882_01/server.112/e17118/statements_4005.htm#SQLRF53681
オンラインで行われると、統計が収集されないため、答えが得られません。
あなたは静かな期間にそれをしなければならないでしょう。