Ludia / REINDEXをバッチで実行する

【追記】
Ludia 0.9ではREINDEXが可能となっているので、既にLudia0.9以前のバージョンを導入している方向けの情報になります。

see also, id:solitary_shell:20061213:1166031150
【/追記】

id:solitary_shell:20061101:1162441618で書いたように現時点のLudiaのバージョン(ludia-0.8.0)ではREINDEXができないので、PerlSQL文にてREINDEXを実行するスクリプトを作成してみました。参考にした情報は、ludia-0.8.0内に含まれるREADMEファイルです。


インデックスの削除

                                  • -

PostgreSQLのインデックスリレーションファイルは、
Ludiaのインデックスファイルは以下の5つから構成されます。
(テーブル空間を使用している場合は、テーブル空間定義時に指定した場所に置かれます。)

  1. PGDATA/base/データベースのOID/インデックスのファイルノード番号
  2. PGDATA/base/データベースのOID/インデックスのファイルノード番号.SEN
  3. PGDATA/base/データベースのOID/インデックスのファイルノード番号.SEN.i
  4. PGDATA/base/データベースのOID/インデックスのファイルノード番号.SEN.i.c
  5. PGDATA/base/データベースのOID/インデックスのファイルノード番号.SEN.l

1 はPostgreSQLのインデックスリレーションファイル、
2〜5はSennaのインデックスファイルです。
2〜5のファイルは手作業で削除する必要があります。

参考として、インデックスのファイルノード番号は以下のようなクエリで取得できます。::

  SELECT relfilenode FROM pg_class WHERE relname = 'index1';

また、データベースのOIDは以下のようなクエリで取得できます。::

  SELECT oid FROM pg_database WHERE datname = 'dbname';

1のファイルについては、DROP INDEXを実行することで削除されます。::

DROP INDEX index1;

ちなみにデータベース名とテーブルスペース名は以下のように作成してあります。

データベース名: sample
テーブルスペース名: sample (/db/pgsql/data/sample)

実際のSQL文は以下になります。

SELECT 'DROP INDEX ' || i.indexname || ';' AS DROP_SQL, 
       i.indexdef || ';' AS CREATE_SQL, 
       tmp.tbs_base || c.relfilenode || '.SEN' AS RM_INDEX_1, 
       tmp.tbs_base || c.relfilenode || '.SEN.i' AS RM_INDEX_2, 
       tmp.tbs_base || c.relfilenode || '.SEN.i.c' AS RM_INDEX_3, 
       tmp.tbs_base || c.relfilenode || '.SEN.l' AS RM_INDEX_4 
FROM
                pg_class c
     INNER JOIN pg_indexes i ON c.relname = i.indexname,
     (
       SELECT t.spclocation || '/' || d.oid  || '/' AS tbs_base
       FROM pg_database d,
            pg_tablespace t
       WHERE d.datname = 'sample'
         AND t.spcname = 'sample'
     ) tmp
WHERE c.relname = 'idx_m_address_senna';

ざっと説明すると、DROP INDEX文、CREATE INDEX文、Sennaのインデックスファイルの削除用のコマンドになります。(Linuxしか想定していません)

実際のSQLの実行結果は以下の通りになります。

sample=>    SELECT 'DROP INDEX ' || i.indexname || ';' AS DROP_SQL, 
sample->           i.indexdef || ';' AS CREATE_SQL, 
sample->           tmp.tbs_base || c.relfilenode || '.SEN' AS RM_INDEX_1, 
sample->           tmp.tbs_base || c.relfilenode || '.SEN.i' AS RM_INDEX_2, 
sample->           tmp.tbs_base || c.relfilenode || '.SEN.i.c' AS RM_INDEX_3, 
sample->           tmp.tbs_base || c.relfilenode || '.SEN.l' AS RM_INDEX_4 
sample->    FROM
sample->                    pg_class c
sample->         INNER JOIN pg_indexes i ON c.relname = i.indexname,
sample->         (
sample(>           SELECT t.spclocation || '/' || d.oid  || '/' AS tbs_base
sample(>           FROM pg_database d,
sample(>                pg_tablespace t
sample(>           WHERE d.datname = 'sample'
sample(>             AND t.spcname = 'sample'
sample(>         ) tmp
sample->    WHERE c.relname = 'idx_m_address_senna';
            drop_sql             |                              create_sql                              |              rm_index_1               |               rm_index_2                |                rm_index_3                 |               rm_index_4                
---------------------------------+----------------------------------------------------------------------+---------------------------------------+-----------------------------------------+-------------------------------------------+-----------------------------------------
 DROP INDEX idx_m_address_senna; | CREATE INDEX idx_m_address_senna ON m_address USING fulltext (city); | /db/pgsql/data/sample/16391/61455.SEN | /db/pgsql/data/sample/16391/61455.SEN.i | /db/pgsql/data/sample/16391/61455.SEN.i.c | /db/pgsql/data/sample/16391/61455.SEN.l
(1 row)

その結果を元にPerlスクリプトで以下のロジックを実装することになります。

  1. インデックスの削除
  2. Sennaインデックスファイルの削除
  3. インデックスの作成

動作確認をして問題がないことを確認した上で、cronに仕込んで自動的にREINDEXを行なうようにします。

see also,