PostgreSQLのユーザーデータベースで、使われているIndex(Select文などからScanされたことがあるIndex)のみ、REINDEXを実行するバッチ(bat)を作成しました。
ソースコードはGitHubで公開しています。
フォルダ/ファイル構成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
C:\Tasks └─reindexTask │ reindex.bat │ ├─dat │ select_index_output.txt │ ├─log │ 20230106.log │ └─sql select_index.sql |
select_index.sql
・「WHERE schemaname not like ‘pg_%’ and schemaname != ‘information_schema’」でPostgreSQLのシステムスキーマは対象外にしています。
・idx_scan、idx_tup_read、idx_tup_fetch いずれも0以下の場合、使われていないIndexだと見なし、REINDEX対象外にしています。
1 2 3 4 5 6 7 8 9 |
SELECT indexrelname FROM pg_stat_user_indexes WHERE relname in ( SELECT tablename FROM pg_tables WHERE schemaname not like 'pg_%' and schemaname != 'information_schema' ) AND (idx_scan > 0 OR idx_tup_read > 0 OR idx_tup_fetch > 0) |
select_index_output.txt
・select_index.sql の実行結果。
1 2 3 4 5 6 7 |
indexrelname --------------------------------------- t_testTableA_pkey t_testTableB_pkey (2 行) |
reindex.bat
・(ホスト名)(データベース名)(データベース ログインユーザ名)(データベース ログインパスワード)を環境に合わせて変更することで実行可能です。
・select_index.sql をPostgreSQLに発行し、抽出されたIndexを対象に REINDEXを実行します。
・「for /f “delims=” %%a in (%SELECT_INDEX_OUTPUT_FILE%) do」でSQL実行結果ファイルを1行づつ読込み、「echo %%a | find “〇〇〇” 1>nul if not ERRORLEVEL 1」で、Index名以外はスキップしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
rem @echo off rem -------------------------------------------------- rem DB接続パラメータ rem -------------------------------------------------- set PGPATH=D:\Tasks\reindexTask set HOSTNAME=(ホスト名) set DBNAME=(データベース名) set USERNAME=(データベース ログインユーザ名) set PGPASSWORD=(データベース ログインパスワード) rem -------------------------------------------------- rem 定数 rem -------------------------------------------------- rem 今日の日付 set YYYYMMDD=%DATE:/=% rem 実行SQLファイル定義 set SELECT_INDEX_FILE=sql\select_index.sql rem SQL実行結果ファイル定義 set SELECT_INDEX_OUTPUT_FILE=dat\select_index_output.txt rem -------------------------------------------------- rem 実行 rem -------------------------------------------------- rem 処理開始 echo %date:/=-% %time:.=,%0 start >log\%YYYYMMDD%.log cd %PGPATH% if not exist "dat" ( rem datフォルダが無ければ作成 mkdir dat\ ) if not exist "log" ( rem logフォルダが無ければ作成 mkdir log\ ) echo %date:/=-% %time:.=,%0 REINDEX対象抽出 start >>log\%YYYYMMDD%.log psql -h %HOSTNAME% -p 5432 -U %USERNAME% -f %SELECT_INDEX_FILE% -d %DBNAME% -o %SELECT_INDEX_OUTPUT_FILE% >> log\%YYYYMMDD%.log echo %date:/=-% %time:.=,%0 REINDEX対象抽出 end >>log\%YYYYMMDD%.log rem REINDEX対象抽出結果を1行ずつ読み込む。Index名以外はスキップする。 for /f "delims=" %%a in (%SELECT_INDEX_OUTPUT_FILE%) do ( echo %%a | find "行" 1>nul if not ERRORLEVEL 1 ( echo %date:/=-% %time:.=,%0 : スキップ[%%a] >> log\%YYYYMMDD%.log ) else ( echo %%a | find "--" 1>nul if not ERRORLEVEL 1 ( echo %date:/=-% %time:.=,%0 : スキップ[%%a] >> log\%YYYYMMDD%.log ) else ( echo %%a | find "indexrelname" 1>nul if not ERRORLEVEL 1 ( echo %date:/=-% %time:.=,%0 : スキップ[%%a] >> log\%YYYYMMDD%.log ) else ( rem Index名なので REINDEXを行う。 echo %date:/=-% %time:.=,%0 : psql -h %HOSTNAME% -p 5432 -U %USERNAME% -c "REINDEX INDEX %%a;" -d %DBNAME% >> log\%YYYYMMDD%.log psql -h %HOSTNAME% -p 5432 -U %USERNAME% -c "REINDEX INDEX %%a;" -d %DBNAME% >> log\%YYYYMMDD%.log ) ) ) ) rem 処理終了 echo %date:/=-% %time:.=,%0 end >>log\%YYYYMMDD%.log |
20230106.log
・reindex.bat 実行ログ。
1 2 3 4 5 6 7 8 9 10 11 |
2023-01-06 17:58:00,070 start 2023-01-06 17:58:00,070 : スキップ[ indexrelname ] 2023-01-06 17:58:00,070 : スキップ[---------------------------------------] 2023-01-06 17:58:00,070 : psql -h (ホスト名) -p 5432 -U (データベース ログインユーザ名) -c "REINDEX INDEX t_testTableA_pkey;" -d (データベース名) REINDEX 2023-01-06 17:58:00,070 : psql -h (ホスト名) -p 5432 -U (データベース ログインユーザ名) -c "REINDEX INDEX t_testTableB_pkey;" -d (データベース名) REINDEX 2023-01-06 17:58:00,070 : スキップ[(2 行)] 2023-01-06 17:58:01,610 end |
コメント