web-dev-qa-db-ja.com

オンラインでのインデックス圧縮候補の決定

以下を実行することで、インデックスが圧縮から利益を得るかどうか、および圧縮に含める列の数を決定できます。

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

問題は、OFFLINEONLINEに変更されると、Index_Statsビューにデータが入力されないことです。インデックスを圧縮するメリットや最適な圧縮を生成する列数をオンラインで決定する方法はありますか?

更新:

http://jonathanlewis.wordpress.com/index-definitions/ は、DBA_IndexesからのDistinct_Keysがnum_rowsよりも「はるかに小さい」場合、インデックスが圧縮に適していることを示します。これは一部には役立ちますが、決定的なものではなく、列数の決定には役立ちません。彼はそのためのいくつかのガイドラインを示していますが、動的SQLの束がなければプログラムで決定できるものは何もありません。

5
Leigh Riffel

圧縮する列の最適数 依存する

  • 各ブロックに収まるエントリの数(ブロックごとに1回だけ格納されるため、これは圧縮された列の数に依存します)
  • 同じプレフィックスを持つエントリの平均数

これらの要素は、テーブルに対して推定できます

目的は、同じプレフィックスを持つすべての行を保持するために必要なブロック数を最小限に抑えながら、圧縮されたプレフィックスのサイズを最大化することです。

データが少なくともある程度均一であると仮定し、導入される少量のオーバーヘッド圧縮を無視すると、次のようにこのアプローチを実装することができます。

ヘルパー関数:

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

オンラインで行われると、統計が収集されないため、答えが得られません。

あなたは静かな期間にそれをしなければならないでしょう。

2
Cell-o