Continue(s)

Twitter:@dn0t_ GitHub:@ogrew

MySQLでレコード数を一々COUNT関数を使わずにサクッと調べる方法

f:id:taiga006:20180304184414p:plain

MySQLを勉強する上でネットからサンプルデータをローカルにダウンロードしていろいろ実験したいわけですが、そのたびに一々

「このサンプルデータにはどれくらいデータが入ってるんだろう?」

show tablesしてdescribeしてcount(*)して…みたいなことをしていたんですが、そんなことする必要がないことを今回学んだのでメモ。

information_schemaというメタデータをまとめたデータベースがあります。ここのTABLESというテーブル(そのまま)からいろんな情報を引っ張ってこれます。

mysql> desc TABLES;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.01 sec)

とにかくいろいろ情報を持ってます。この内TABLE_ROWSというカラムから各データベースの各テーブルのレコード数を取得できちゃいます。

つまり今ままで

mysql> use sakila;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------------------+
| Tables_in_sakila           |
+----------------------------+
| actor                      |
| actor_info                 |
| address                    |
| category                   |
| city                       |
| country                    |
| customer                   |
| customer_list              |
| film                       |
| film_actor                 |
| film_category              |
| film_list                  |
| film_text                  |
| inventory                  |
| language                   |
| nicer_but_slower_film_list |
| payment                    |
| rental                     |
| sales_by_film_category     |
| sales_by_store             |
| staff                      |
| staff_list                 |
| store                      |
+----------------------------+
23 rows in set (0.01 sec)

mysql> desc actor;
+-------------+----------------------+------+-----+-------------------+-----------------------------+
| Field       | Type                 | Null | Key | Default           | Extra                       |
+-------------+----------------------+------+-----+-------------------+-----------------------------+
| actor_id    | smallint(5) unsigned | NO   | PRI | NULL              | auto_increment              |
| first_name  | varchar(45)          | NO   |     | NULL              |                             |
| last_name   | varchar(45)          | NO   | MUL | NULL              |                             |
| last_update | timestamp            | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+----------------------+------+-----+-------------------+-----------------------------+
4 rows in set (0.00 sec)

mysql> select count(*) from actor;
+----------+
| count(*) |
+----------+
|      200 |
+----------+
1 row in set (0.00 sec)

としていたのを

mysql> use information_schema;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select TABLE_SCHEMA, TABLE_NAME, TABLE_ROWS FROM TABLES WHERE TABLE_SCHEMA = 'sakila';
+--------------+----------------------------+------------+
| TABLE_SCHEMA | TABLE_NAME                 | TABLE_ROWS |
+--------------+----------------------------+------------+
| sakila       | actor                      |        200 |
| sakila       | actor_info                 |       NULL |
| sakila       | address                    |        603 |
| sakila       | category                   |         16 |
| sakila       | city                       |        600 |
| sakila       | country                    |        109 |
| sakila       | customer                   |        599 |
| sakila       | customer_list              |       NULL |
| sakila       | film                       |       1000 |
| sakila       | film_actor                 |       5462 |
| sakila       | film_category              |       1000 |
| sakila       | film_list                  |       NULL |
| sakila       | film_text                  |       1000 |
| sakila       | inventory                  |       4581 |
| sakila       | language                   |          6 |
| sakila       | nicer_but_slower_film_list |       NULL |
| sakila       | payment                    |      16086 |
| sakila       | rental                     |      16005 |
| sakila       | sales_by_film_category     |       NULL |
| sakila       | sales_by_store             |       NULL |
| sakila       | staff                      |          2 |
| sakila       | staff_list                 |       NULL |
| sakila       | store                      |          2 |
+--------------+----------------------------+------------+
23 rows in set (0.00 sec)

の一つのクエリで調べたいことがわかる、というわけです。

ただこのTABLE_ROWSの値は性格では内容で、実際にレコード数の多い(あと更新頻度も高い)テーブルで実験してみればわかりますがcount(*)で調べた数字と結構ズレてたりします。笑

ただコードを最初にも述べたようにサンプルデータと割り切って手元で色々遊んでみたいときなどに最初にサクッと調べる分には十分だと思われます。

他にもTABLESテーブルには様々な情報がまとまっている模様。 使いこなしたい。