监控数据库的应用程序可能会频繁地使用 INFORMATION_SCHEMA
表。为了高效地编写这些表的查询,请遵循以下一般指南:
-
尽量查询
INFORMATION_SCHEMA
视图表,这些表基于数据字典表。 -
尽量查询静态元数据。选择列或使用动态元数据的检索条件会增加处理动态元数据的开销。
在 INFORMATION_SCHEMA
查询中,数据库和表名的比较行为可能与您期望的不同。详细信息,请参阅 第 12.8.7 节,“在 INFORMATION_SCHEMA 搜索中使用排序”。
这些 INFORMATION_SCHEMA
表是基于数据字典表的视图,因此查询这些表会从数据字典中检索信息:
CHARACTER_SETS
CHECK_CONSTRAINTS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
EVENTS
FILES
INNODB_COLUMNS
INNODB_DATAFILES
INNODB_FIELDS
INNODB_FOREIGN
INNODB_FOREIGN_COLS
INNODB_INDEXES
INNODB_TABLES
INNODB_TABLESPACES
INNODB_TABLESPACES_BRIEF
INNODB_TABLESTATS
KEY_COLUMN_USAGE
PARAMETERS
PARTITIONS
REFERENTIAL_CONSTRAINTS
RESOURCE_GROUPS
ROUTINES
SCHEMATA
STATISTICS
TABLES
TABLE_CONSTRAINTS
TRIGGERS
VIEWS
VIEW_ROUTINE_USAGE
VIEW_TABLE_USAGE
某些类型的值,即使对于非视图 INFORMATION_SCHEMA
表,也是通过从数据字典中查找检索的。这些值包括数据库和表名、表类型和存储引擎。
某些 INFORMATION_SCHEMA
表包含提供表统计信息的列:
STATISTICS.CARDINALITY
TABLES.AUTO_INCREMENT
TABLES.AVG_ROW_LENGTH
TABLES.CHECKSUM
TABLES.CHECK_TIME
TABLES.CREATE_TIME
TABLES.DATA_FREE
TABLES.DATA_LENGTH
TABLES.INDEX_LENGTH
TABLES.MAX_DATA_LENGTH
TABLES.TABLE_ROWS
TABLES.UPDATE_TIME
这些列表示动态表元数据,即表内容变化时的信息。
默认情况下,MySQL 从 mysql.index_stats
和 mysql.innodb_table_stats
字典表中检索缓存的值,以便检索这些列的统计信息,这比直接从存储引擎中检索统计信息更高效。如果缓存的统计信息不可用或已过期,MySQL 将从存储引擎中检索最新的统计信息,并将其缓存在 mysql.index_stats
和 mysql.innodb_table_stats
字典表中。随后的查询将检索缓存的统计信息,直到缓存的统计信息过期。服务器重启或第一次打开 mysql.index_stats
和 mysql.innodb_table_stats
表不会自动更新缓存的统计信息。
会话变量 information_schema_stats_expiry
定义了缓存统计信息的过期时间,默认为 86400 秒(24 小时),但可以将时间期限延长到一年。
要在任何时候为给定表更新缓存的值,请使用 ANALYZE TABLE
。
查询统计信息列不会在以下情况下存储或更新 mysql.index_stats
和 mysql.innodb_table_stats
字典表中的统计信息:
-
当缓存的统计信息未过期时。
-
当
information_schema_stats_expiry
设置为 0 时。 -
当服务器处于
read_only
、super_read_only
、transaction_read_only
或innodb_read_only
模式时。 -
当查询也检索性能模式数据时。
information_schema_stats_expiry
是一个会话变量,每个客户端会话可以定义自己的过期值。从存储引擎中检索的统计信息并缓存在 mysql.index_stats
和 mysql.innodb_table_stats
字典表中的统计信息可供其他会话使用。
如果启用了 innodb_read_only
系统变量,ANALYZE TABLE
可能会失败,因为它无法更新数据字典中的统计信息表,这些表使用 InnoDB
。对于 ANALYZE TABLE
操作,例如,如果它更新了表本身(例如,如果它是一个 MyISAM
表),可能会失败。要获取更新的分布统计信息,请设置 information_schema_stats_expiry=0
。
对于作为数据字典表视图的 INFORMATION_SCHEMA
表,基础数据字典表上的索引允许优化器构建高效的查询执行计划。要查看优化器的选择,请使用 EXPLAIN
。要查看服务器执行 INFORMATION_SCHEMA
查询时使用的查询,请使用 SHOW WARNINGS
,紧接着使用 EXPLAIN
。
考虑以下语句,它标识了 utf8mb4
字符集的排序规则:
mysql> SELECT COLLATION_NAME
FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY
WHERE CHARACTER_SET_NAME = 'utf8mb4';
+----------------------------+
| COLLATION_NAME |
+----------------------------+
| utf8mb4_general_ci |
| utf8mb4_bin |
| utf8mb4_unicode_ci |
| utf8mb4_icelandic_ci |
| utf8mb4_latvian_ci |
| utf8mb4_romanian_ci |
| utf8mb4_slovenian_ci |
...
服务器如何处理该语句?要找到答案,请使用 EXPLAIN
:
mysql> EXPLAIN SELECT COLLATION_NAME
FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY
WHERE CHARACTER_SET_NAME = 'utf8mb4'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: cs
partitions: NULL
type: const
possible_keys: PRIMARY,name
key: name
key_len: 194
ref: const
rows: 1
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: col
partitions: NULL
type: ref
possible_keys: character_set_id
key: character_set_id
key_len: 8
ref: const
rows: 68
filtered: 100.00
Extra: NULL
2 rows in set, 1 warning (0.01 sec)
要查看满足该语句的查询,请使用 SHOW WARNINGS
:
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select `mysql`.`col`.`name` AS `COLLATION_NAME`
from `mysql`.`character_sets` `cs`
join `mysql`.`collations` `col`
where ((`mysql`.`col`.`character_set_id` = '45')
and ('utf8mb4' = 'utf8mb4'))
如 SHOW WARNINGS
所示,服务器将该查询处理为对 COLLATION_CHARACTER_SET_APPLICABILITY
的查询,实际上是对 mysql
系统数据库中的 character_sets
和 collations
数据字典表的查询。