More info...

2009-02-16

InnoDBテーブルスペースの空き領域

以前の投稿でも書いたが、InnoDBのテーブルスペースは一度大きくなってしまうと縮小することができない。ならば実際にはどれだけのスペースが使われているのか?という疑問が沸いてくることだろう。それは、innodb_file_per_tableオプションを利用しているときとそうでないときで見方が違う。

innodb_file_per_tableオプションを利用していない場合には、InnoDBテーブルスペース内の空き領域は、SHOW TABLE STATUSコマンドで確認することができる。

mysql> SHOW TABLE STATUS LIKE 'tbl';

MySQL 5.0または5.1.23以前ではCommentフィールドに、MySQL 5.1.24以降ではData_freeフィールドに空き領域の容量が表示される。MySQL 5.1のGAバージョンは5.1.30なので、実質的には「5.1ではData_freeフィールドに空き領域が表示されるようになった」といえる。また、innodb_file_per_tableオプションを利用していない場合には、各テーブルは共通のテーブルスペースを利用するためどのテーブルに対してSHOW TABLE STATUSコマンドを実行した場合でも同じ空き領域が表示される。

innodb_file_per_tableオプションを利用している場合には、各テーブルが利用しているデータファイルにおける未使用領域を、テーブルごとにSHOW TABLE STATUSコマンドで表示することが可能だ。共通テーブルスペース上にテーブルが一つもない場合は、共通テーブルスペースの空き領域を表示する方法はない。どうしても気になるなら共通テーブルスペース上にテーブルを作成しておけばいいが、それほど気にしなくても問題はないだろう。(innodb_file_per_tableオプションを利用しているわけだから。)

MySQL 5.0以降は、INFORMATION_SCHEMAという便利なシロモノがある。SHOW TABLE STATUSコマンドを利用する代わりに、INFOMATION_SCHEMA.TABLESテーブルを参照することで同様の情報を表示することが可能であり、innodb_file_per_tableオプション利用時は次のように利用することで、全てのテーブルに関する情報を一括表示することが可能だ。

mysql> SELECT TABLE_SCHEMA,TABLE_NAME,DATA_FREE
    -> FROM INFORMATION_SCHEMA.TABLES
    -> WHERE ENGINE='innodb';
mysql> SELECT TABLE_SCHEMA,SUM(DATA_FREE)
    -> FROM INFORMATION_SCHEMA.TABLES
    -> WHERE ENGINE='innodb'
    -> GROUP BY TABLE_SCHEMA WITH ROLLUP;

SHOWコマンドの出力は加工することは出来ないが、INFORMATION_SCHEMAは好きなようにWHERE句で絞り込みを行ったり集計したりすることができるので便利なのだ。

ところで、Data_freeの数値はInnoDBにおいてどの程度信頼できるのだろうか。

InnoDBのテーブルスペース内では、データは16KBのページ単位で管理されており、さらに64個の連続するページから成るエクステントにグループ化されている。InnoDBテーブルからデータを削除すると、対応するBツリーインデックスが縮小される。これによって、他のテーブルに対して空き領域が再利用できるかどうかは、削除のパターンがテーブルスペースの個々のページやエクステントを解放するかどうかによる。エクステントが解放された場合には、そのエクステントは他のテーブルによって再利用されるが、個々のページやページの一部だけが開放されただけの場合には他のテーブルによって再利用されることはない。つまり、Data_freeは使用されていないエクステントのサイズであり、ページ単位で見ると空き領域がある場合があるということだ。しかしながら、領域を再利用できるかどうかはエクステント全体が空いているかどうかで決まるため、Data_freeはほぼ正確な空き領域を示していると言える。

最後にちょっとだけ内部構造的な話。SHOW TABLE STATUSやINFORMATION_SCHEMAの情報は、最終的にはinnobase/fsp/fsp0fsp.c内のfsp_get_available_space_in_free_extents()関数によって値が取得される。関数の引数はテーブルスペースのIDである。下記は関数の末尾からの抜粋である。

return((ullint)(n_free - reserve)
* FSP_EXTENT_SIZE
* (UNIV_PAGE_SIZE / 1024));

空き領域(n_free)から予約された領域(reserve)を引いたものに、一つのエクステントに含まれるページ数(FSP_EXTENT_SIZE=64)を掛けて、さらにページサイズ(UNIV_PAGE_SIZE/1024=16kb)を掛けたものを返しているというワケである。興味のある人はソースコードを覗いてみよう。

0 件のコメント:

コメントを投稿