Documentation Home
MySQL 8.0 Reference Manual
Related Documentation Download this Manual

MySQL 8.0 Reference Manual  /  ...  /  Optimizing INFORMATION_SCHEMA Queries

9.2.4 Optimizing INFORMATION_SCHEMA Queries

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_SCHEMA tables 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.

Note

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:

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, use ANALYZE 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, use ANALYZE TABLE again.

  • To use the latest statistics, ANALYZE TABLE is 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.


User Comments
  Posted by Shlomi Noach on October 3, 2011
The example for joining TABLES with COLUMNS shows good EXPLAIN plan for TABLES, but poor EXPLAIN plan for columns, since the table name and schema for COLUMNS cannot be deduced ahead.
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)

Sign Up Login You must be logged in to post a comment.