MySQL道普請便り

第166回 Performance_schema関数

この記事を読むのに必要な時間:およそ 3 分

概要

performance_schemaを参照するときに,生のデータだとピコ秒やbytesで格納されており,自前で計算したりsysスキーマの関数を使って出力をしていたかと思います。このsysスキーマにあった関数の一部は,8.0.16以降のバージョンではPerformance_schema関数として組み込み関数となりました。

今回はこれらの関数について紹介します。なお,検証に利用しているMySQLのバージョンは8.0.28を利用しております。

format_bytes()

format_bytes()関数は,引数にバイト数を与えることで値と単位に変換して文字列を返すようになります。たとえば,引数に1023を与えた場合は1023 bytesという文字列が表示され,536870912を与えると512.00 MiBが表示されるように,小数点以下2桁に丸められたバイト数と,3桁以上の整数が表示されます。

実際にいくつか数値を投げて確認してみます。

mysql> SELECT FORMAT_BYTES(1023), FORMAT_BYTES(536870912), FORMAT_BYTES(47193858765) ;
+--------------------+-------------------------+---------------------------+
| FORMAT_BYTES(1023) | FORMAT_BYTES(536870912) | FORMAT_BYTES(47193858765) |
+--------------------+-------------------------+---------------------------+
| 1023 bytes         | 512.00 MiB              | 43.95 GiB                 |
+--------------------+-------------------------+---------------------------+
1 row in set (0.00 sec)

それぞれの引数に対して,適切な単位に変換された数値が返ってきました⁠。

これはファイルサイズや,データ量を表示するデータに対して実行する時に利用すると便利です。例として,第56回 InnoDBテーブルサイズのいろいろな確認方法で出てきたSQLに関してFORMAT_BYTES()を利用して表示してみたいと思います。

mysql> SELECT NAME,FILE_SIZE,FORMAT_BYTES(FILE_SIZE), ALLOCATED_SIZE, FORMAT_BYTES(ALLOCATED_SIZE) FROM information_schema.innodb_tablespaces WHERE NAME = 'd1/dummy';
+----------+-----------+-------------------------+----------------+------------------------------+
| NAME     | FILE_SIZE | FORMAT_BYTES(FILE_SIZE) | ALLOCATED_SIZE | FORMAT_BYTES(ALLOCATED_SIZE) |
+----------+-----------+-------------------------+----------------+------------------------------+
| d1/dummy |   9437184 | 9.00 MiB                |        9437184 | 9.00 MiB                     |
+----------+-----------+-------------------------+----------------+------------------------------+
1 row in set (0.00 sec)

$ ll -h /data/sample_mysql/d1/dummy.ibd
-rw-r----- 1 mysql mysql 9.0M Apr 30  2020 /data/sample_mysql/d1/dummy.ibd

単位が変換されて確認することができました。

これはテーブルサイズだけでなく,buffer_poolのサイズ確認や,テーブルごとのメモリのサイズを調べるときなどに有用です。

※)
単位の変換は10の3乗ごと(キロ,メガ,テラ)ではなく,1024のn乗ごと(キビ,メビ,テビ)であるのに注意してください。

sys.format_bytes()との違い

8.0.16以前のバージョンにも,sysスキーマmysql/mysql-sysにformat_bytes()がありました。当時のformat_bytes()はPiBまでしか表示できないものでした。しかし,WL#13439にあるように,現在はsys.format_bytes()を実行すると組み込み関数のformat_bytes()が実行されるようになっています。

ただし公式ドキュメントにもあるように,sys.format_bytesの利用は非推奨となっており,将来のバージョンで削除される予定があるため,組み込み関数のformat_bytes()を使用するように修正してください。

format_pico_time()

format_pico_time()関数は,ピコ秒単位で表示されるデータに対して使用することで,単位を変換して表示するようになります。たとえば,引数に3を与えた場合は3 psと表示されますが,300000000000000を与えると5.00 min(300秒)が表示されます。

例として,第120回 events_statements_summary_by_digestテーブルのパラメータのperformance_schema_max_digest_sample_ageで解説されたQUERY_SAMPLE_TIMER_WAITがピコ秒なので,これをformat_pico_time()関数を使って表示を変えてみます。

mysql> SELECT DIGEST_TEXT, COUNT_STAR, SUM_ROWS_SENT, SUM_ROWS_EXAMINED, FIRST_SEEN, FORMAT_PICO_TIME(QUERY_SAMPLE_TIMER_WAIT) FROM performance_schema.events_statements_summary_by_digest where DIGEST_TEXT like '%dummy%'\G
*************************** 1. row ***************************
                              DIGEST_TEXT: ANALYZE TABLE `d1` . `dummy`
                               COUNT_STAR: 1
                            SUM_ROWS_SENT: 0
                        SUM_ROWS_EXAMINED: 0
                               FIRST_SEEN: 2022-02-20 20:36:39.163430
FORMAT_PICO_TIME(QUERY_SAMPLE_TIMER_WAIT): 10.06 s

ピコ秒で表示されるデータがs(seconds:秒)に変わって表示されているのが確認できます。

sys.format_time()との違い

sysスキーマにはformat_time()という似た関数が存在します。この関数と挙動はほぼ同じですが,後述する以下の点が違います。

また,format_bytes()と同様に,こちらも8.0.16以降非推奨となりました。MySQL 8.0.28現在は両方利用可能ですが,将来sys.format_time()が削除予定ですので,format_pico_time()を利用するようにしましょう。

分の表示

組み込み関数format_pico_time()の方では分(minutes)はminで表示されますが,sysのformat_time()はmと表示されます。

mysql> SELECT format_pico_time(300000000000000), sys.format_time(300000000000000);
+-----------------------------------+----------------------------------+
| format_pico_time(300000000000000) | sys.format_time(300000000000000) |
+-----------------------------------+----------------------------------+
| 5.00 min                          | 5 m                              |
+-----------------------------------+----------------------------------+
1 row in set (0.01 sec)
w(week)の削除

組み込み関数format_pico_time()の方では最大の単位はd(day:日)ですが,sysのformat_time()はw(week:週)で表示されます。

mysql> SELECT format_pico_time(724800000000000000), sys.format_time(724800000000000000);
+--------------------------------------+-------------------------------------+
| format_pico_time(724800000000000000) | sys.format_time(724800000000000000) |
+--------------------------------------+-------------------------------------+
| 8.39 d                               | 1.2 w                               |
+--------------------------------------+-------------------------------------+
1 row in set (0.00 sec)

その他のPerformance_schema関数

WL#13439にもあるように,バージョン8.0.16でps_thread_id()関数もsysスキーマから組み込み関数へと変わりました。

これもsysのps_thread_id()とほぼ同じですが,引数にNULLを与えた時の挙動が違います。sysスキーマでは自身のパフォーマンススキーマに対する接続スレッドIDが表示されていましたが,組み込み関数ではNULLが表示されるようになりました。

mysql> SELECT ps_thread_id(null), sys.ps_thread_id(null);
+--------------------+------------------------+
| ps_thread_id(null) | sys.ps_thread_id(null) |
+--------------------+------------------------+
|               NULL |                     65 |
+--------------------+------------------------+
1 row in set (0.00 sec)

ただし,ps_current_thread_id()という自身のパフォーマンススキーマに対する接続スレッドIDを返す関数が追加されています。

まとめ

今回はPerformance_schema関数ということで,バージョン8.0.16以降でsysスキーマから組み込み関数となった3つの関数を紹介しました。performance_schemaのデータに関してはsizeや時間がそれぞれbytes,ピコ秒で格納されていることが多いため,積極的に利用して桁数を間違えないようにしましょう。

著者プロフィール

深町日出海(ふかまちひでみ)

GMOメディア株式会社のデータベースエンジニア。主にOracleとMySQLを担当。得意なプログラム言語はJava。MySQLの好きなところはTABLEやINDEXの識別子に64byteまで使えるところ。

Twitter:@lhfukamachi