UN-USED INDEX

unused index

RDBSのパフォーマンスは、SQL構文、Index、データサイズ等に依存していますが、SQL構文の得手不得手はデータベースの種類にもよって、オプティマイザーの処理が異なるので変わってきます。それぞれのRDBMSが苦手な処理を避けて書き換える事で対応する事が出来るでしょう。データサイズが経年と共に大きくなってきたら、パーティションを検討したり、古いデータを削除したりして対応する事も検討が必要になってくるかと思います。Indexに関しては、データベースを設計する段階で予め考慮してIndexを付けておくと同時に、運用の中で重い処理が出てきたらwhere句の処理で選択されている列を指定してインデックスを付けてあげると良いでしょう。その場合も複合インデックス等の場合は、SQLの処理によってはインデックスが使われない事があるので順番も気にすると良い場合もあるでしょう。インデックスは参照処理を高速化すると同時に、Insert、Update、Delete等の書き込み処理の場合にはインデックス更新を伴うのでシステム的にオーバーヘッドになります。不要なインデックスが存在している場合は適宜、削除してオーバヘッドを減らすと同時に、不要なディスク容量が増加しないように留意しておくと良いでしょう。

PostgreSQLの場合はpg_stat_user_indexes を利用

In case of PostgreSQL

rails_app=# \c development 
You are now connected to database "development" as user "postgres".
taskleaf_development=# SELECT indexrelname, idx_scan, idx_tup_read, idx_tup_fetch FROM pg_stat_user_indexes;
                indexrelname                 | idx_scan | idx_tup_read | idx_tup_fetch 
---------------------------------------------+----------+--------------+---------------
 schema_migrations_pkey                      |       30 |          195 |           195
 ar_internal_metadata_pkey                   |        3 |            2 |             2
 notes_pkey                                  |     1455 |         1769 |          1751
 users_pkey                                  |     2202 |         2202 |          2202
 index_users_on_email                        |      108 |           94 |            94
 index_tasks_on_user_id                      |      306 |         1455 |          1453
 active_storage_blobs_pkey                   |      112 |          112 |           112
 index_active_storage_blobs_on_key           |        0 |            0 |             0
 active_storage_attachments_pkey             |        0 |            0 |             0
 index_active_storage_attachments_on_blob_id |        0 |            0 |             0
 index_active_storage_attachments_uniqueness |      367 |           46 |            46
 kbis_pkey                                   |        0 |            0 |             0
(12 rows)

taskleaf_development=# 

※ 起動してからの統計です。

pg_stat_user_indexes
  • Script for finding unused-index on PG.

https://github.com/rdbms-at-twitter/PostgreSQL/blob/master/find_unused_index.sql

此方のSQLでは使われて無いIndexと設定されているテーブルも確認する事が可能です。

SELECT s.relname AS table_name,
       indexrelname AS index_name,
       CASE WHEN i.indisunique THEN 'Y'
       ELSE 'N'
       END AS unique,
       idx_scan AS index_scans,
       idx_scan AS idx_tup_read,
       idx_scan AS idx_tup_fetch,
       pg_size_pretty(pg_relation_size(quote_ident(s.indexrelname)::text)) AS index_size
FROM   pg_catalog.pg_stat_user_indexes s,
       pg_index i
WHERE  i.indexrelid = s.indexrelid
       and s.idx_scan = 0
       and s.idx_tup_read = 0
       and s.idx_tup_fetch = 0
       and i.indisunique <> 'y';

重複したIndexを確認するSQLの場合は以下の様になります。

SELECT   indrelid::regclass table_name,
         att.attname column_name,
         amname index_method
FROM     pg_index i,
         pg_class c,
         pg_opclass o,
         pg_am a,
         pg_attribute att
WHERE    o.oid = ALL (indclass) 
AND      att.attnum = ANY(i.indkey)
AND      a.oid = o.opcmethod
AND      att.attrelid = c.oid
AND      c.oid = i.indrelid
GROUP BY table_name, 
         att.attname,
         indclass,
         amname, indkey
HAVING count(*) > 1;

MySQLの場合はSYS Schemaを利用

In case of MySQL

起動してから利用されてないIndexを特定(schema_unused_indexes)

root@localhost [sys]> select * from sys.schema_unused_indexes limit 5;
+---------------+--------------------+-----------------------------+
| object_schema | object_name        | index_name                  |
+---------------+--------------------+-----------------------------+
| APP           | FTS_Tweets         | idx_mecab_text              |
| APP           | FTS_Tweets2        | idx_mecab_text              |
| APP           | FTS_Tweets20200518 | idx_mecab_text              |
| APP           | FTS_Tweets3        | idx_mecab_text              |
| APP           | password_resets    | password_resets_email_index |
+---------------+--------------------+-----------------------------+
5 rows in set (0.01 sec)


root@localhost [sys]> select * from sys.schema_index_statistics limit 1\G
*************************** 1. row ***************************
  table_schema: APP
    table_name: sessions
    index_name: sessions_id_unique
 rows_selected: 14111
select_latency: 654.74 ms
 rows_inserted: 0
insert_latency:   0 ps
  rows_updated: 705
update_latency: 252.13 ms
  rows_deleted: 6341
delete_latency: 127.89 ms
1 row in set (0.00 sec)

root@localhost [sys]> 

※起動してからの統計になるので、暫く運用してから利用していないインデックスを確認して下さい。

≒ 起動時は殆どがUn-Used Indexになっています。

重複したインデックスの特定と削除 ( schema_redundant_indexes )

このViewを利用すると、重複したインデックスと対象インデックスを削除するためのDDLを表示してくれます。

root@localhost [sys]> select * from  sys.schema_redundant_indexes\G
*************************** 1. row ***************************
              table_schema: confirm
                table_name: memo
      redundant_index_name: idx_text2
   redundant_index_columns: data
redundant_index_non_unique: 1
       dominant_index_name: idx_text1
    dominant_index_columns: data
 dominant_index_non_unique: 1
            subpart_exists: 1
            sql_drop_index: ALTER TABLE `confirm`.`memo` DROP INDEX `idx_text2`
1 row in set (0.01 sec)

root@localhost [sys]> 
schema_redundant_indexes

MySQLとPostgreSQLの実行プランの基本的な確認方法

その他、インデックスに関しての理解

データベースによって利用可能なインデックスに差異はありますが、基本的に考え方としては大きな差異は無いので、インデックス作成時に以下のページも参考になるかと思います。

遅いインデックス パートI

遅いインデックス パートII

複合インデックス

カテゴリー:

最近のコメント

表示できるコメントはありません。