Applications that monitor databases may make frequent use of
INFORMATION_SCHEMA tables. To write queries
for these tables most efficiently, use the following general
guidelines:
Try to query only
INFORMATION_SCHEMAtables that are views on data dictionary tables.Try to query only for static metadata. Selecting columns or using retrieval conditions for dynamic metadata along with static metadata adds overhead to process the dynamic metadata.
Comparison behavior for database and table names in
INFORMATION_SCHEMA queries might differ
from what you expect. For details, see
Section 11.1.8.8, “Collation and INFORMATION_SCHEMA Searches”.
These INFORMATION_SCHEMA tables are
implemented as views on data dictionary tables, so queries on
them retrieve information from the data dictionary:
CHARACTER_SETS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY COLUMNS KEY_COLUMN_USAGE SCHEMATA STATISTICS TABLES TABLE_CONSTRAINTS VIEWS
Some types of values, even for non-view
INFORMATION_SCHEMA tables, are retrieved by
lookups from the data dictionary. This includes values such as
database and table names, table types, and storage engines.
Some INFORMATION_SCHEMA tables contain
columns that provide table statistics, such as
CARDINALITY in
STATISTICS and
DATA_LENGTH, INDEX_LENGTH,
and AUTO_INCREMENT in
TABLES.
The server has two sources from which to retrieve table
statistics. The STATISTICS and
TABLES tables contain cached
statistics, whereas the
STATISTICS_DYNAMIC
and
TABLES_DYNAMIC
tables contain the latest statistics, obtained directly from
storage engines.
To write queries that retrieve table statistics, select from
STATISTICS and
TABLES and set the
information_schema_stats system
variable to control which statistics source the server uses:
When
information_schema_statsisCACHED(the default), queries onSTATISTICSandTABLESretrieve the cached statistics in those tables.When
information_schema_statsisLATEST, the server treats queries onSTATISTICSandTABLESas queries for the latest statistics stored in theSTATISTICS_DYNAMICandTABLES_DYNAMICtables. The server performs this substitution internally. You should write queries using the table name without the_DYNAMICsuffix. For example, wheninformation_schema_statsisLATEST, the server treats this statement:SELECT * FROM INFORMATION_SCHEMA.TABLES;
as though you had written this statement:
SELECT * FROM INFORMATION_SCHEMA.TABLES_DYNAMIC;
To determine how to set
information_schema_stats,
consider the tradeoffs:
When the server starts, the cached statistics are
NULL. To update them for a given table, useANALYZE TABLE. This incurs a one-time statistics-calculation cost, but the cached statistics remain up to date to the extent that the table changes slowly. To update the cached statistics at any time thereafter, useANALYZE TABLEagain.To use the latest statistics,
ANALYZE TABLEis not needed, but queries that retrieve statistics incur somewhat higher execution cost.
Set the global
information_schema_stats value
to determine the default used initially by all sessions.
Individual sessions can set the session
information_schema_stats value
to override the global value as desired.
For INFORMATION_SCHEMA tables implemented as
views on data dictionary tables, indexes on the underlying data
dictionary tables permit the optimizer to construct efficient
query execution plans. To see the choices made by the optimizer,
use EXPLAIN. To also see the
query used by the server to execute an
INFORMATION_SCHEMA query, use
SHOW WARNINGS immediately
following EXPLAIN.
Consider this statement, which identifies collations for the
utf8 character set:
mysql>SELECT COLLATION_NAME->FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY->WHERE CHARACTER_SET_NAME = 'utf8';+--------------------------+ | COLLATION_NAME | +--------------------------+ | utf8_general_ci | | utf8_tolower_ci | | utf8_bin | | utf8_unicode_ci | | utf8_icelandic_ci | | utf8_latvian_ci | | utf8_romanian_ci | ...
How does the server process that statement? To find out, use
EXPLAIN:
mysql>EXPLAIN SELECT COLLATION_NAME->FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY->WHERE CHARACTER_SET_NAME = 'utf8'\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: 28 filtered: 100.00 Extra: NULL 2 rows in set, 1 warning (0.01 sec)
To see the query used to statisfy that statement, use
SHOW WARNINGS:
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select `col`.`name` AS `COLLATION_NAME`
from `mysql`.`character_sets` `cs`
join `mysql`.`collations` `col`
where ((`col`.`character_set_id` = '33')
and ('utf8' = 'utf8'))
As indicated by SHOW WARNINGS,
the server handles the query on
COLLATION_CHARACTER_SET_APPLICABILITY.
as a query on the character_sets and
collations data dictionary tables from the
mysql system database.
But this is just due to poor optimizer's work.
Here's how to get the same results, but with far better execution plan; we push the constants down to COLUMNS:
EXPLAIN SELECT B.TABLE_NAME
-> FROM INFORMATION_SCHEMA.TABLES AS A, INFORMATION_SCHEMA.COLUMNS AS B
-> WHERE A.TABLE_SCHEMA = 'test'
-> AND A.TABLE_NAME = 't1'
-> AND B.TABLE_NAME = 't1'
-> AND B.TABLE_SCHEMA = 'test'
->
-> \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: ALL
possible_keys: NULL
key: TABLE_SCHEMA,TABLE_NAME
key_len: NULL
ref: NULL
rows: NULL
Extra: Using where; Skip_open_table; Scanned 0 databases
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: B
type: ALL
possible_keys: NULL
key: TABLE_SCHEMA,TABLE_NAME
key_len: NULL
ref: NULL
rows: NULL
Extra: Using where; Open_frm_only; Scanned 0 databases; Using join buffer
2 rows in set (0.00 sec)