8.2.3 Оптимизация запросов к INFORMATION_SCHEMA
Приложения, которые отслеживают базы данных, могут часто обращаться к таблицам INFORMATION_SCHEMA. Определенные типы запросов к таблицам INFORMATION_SCHEMA могут быть оптимизированы для более быстрого выполнения. Цель состоит в минимизации операций с файлами (например, сканирования каталога или открытия файла таблицы) для сбора информации, которая составляет эти динамические таблицы.
Поведение сравнения имён баз данных и таблиц в запросах к INFORMATION_SCHEMA может отличаться от ожидаемого. Подробности см. в разделе 10.8.7 «Использование сортировки в запросах к INFORMATION_SCHEMA».
1) Попытка использовать постоянные значения поиска для имён баз данных и таблиц в предложении WHERE
Вы можете использовать этот принцип следующим образом:
Для поиска баз данных или таблиц используйте выражения, которые вычисляются в константу, такие как литеральные значения, функции, возвращающие константу, или скалярные подзапросы.
Избегайте запросов, использующих неконстантное значение поиска имени базы данных (или отсутствие значения поиска), поскольку они требуют сканирования каталога данных для поиска совпадающих имён каталогов баз данных.
Внутри базы данных избегайте запросов, использующих неконстантное значение поиска имени таблицы (или отсутствие значения поиска), поскольку они требуют сканирования каталога базы данных для поиска совпадающих файлов таблиц.
Этот принцип применим к таблицам INFORMATION_SCHEMA, показанным в следующей таблице, которая показывает столбцы, для которых постоянное значение поиска позволяет серверу избежать сканирования каталога. Например, если вы выбираете из TABLES, использование постоянного значения поиска для TABLE_SCHEMA в предложении WHERE позволяет избежать сканирования каталога данных.
| Таблица | Столбец для избежания сканирования каталога данных | Столбец для избежания сканирования каталога базы данных |
|---|---|---|
COLUMNS | TABLE_SCHEMA | TABLE_NAME |
KEY_COLUMN_USAGE | TABLE_SCHEMA | TABLE_NAME |
PARTITIONS | TABLE_SCHEMA | TABLE_NAME |
REFERENTIAL_CONSTRAINTS | CONSTRAINT_SCHEMA | TABLE_NAME |
STATISTICS | TABLE_SCHEMA | TABLE_NAME |
TABLES | TABLE_SCHEMA | TABLE_NAME |
TABLE_CONSTRAINTS | TABLE_SCHEMA | TABLE_NAME |
TRIGGERS | EVENT_OBJECT_SCHEMA | EVENT_OBJECT_TABLE |
VIEWS | TABLE_SCHEMA | TABLE_NAME |
Преимущество запроса, ограниченного определённым именем базы данных, заключается в том, что проверка должна проводиться только для указанного каталога базы данных. Пример:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test';
Использование литерального имени базы данных test позволяет серверу проверять только каталог базы данных test, независимо от количества баз данных. В противоположность этому, следующий запрос менее эффективен, поскольку он требует сканирования каталога данных для определения имён баз данных, соответствующих шаблону 'test%':
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA LIKE 'test%';
Для запроса, ограниченного определённым именем таблицы, проверка должна проводиться только для указанной таблицы в соответствующем каталоге базы данных. Пример:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 't1';
Использование литерального имени таблицы t1 позволяет серверу проверять только файлы для таблицы t1, независимо от количества таблиц в базе данных test. В противоположность этому, следующий запрос требует сканирования каталога базы данных test для определения имён таблиц, соответствующих шаблону 't%':
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%';
Следующий запрос требует сканирования каталога базы данных для определения соответствующих имён баз данных для шаблона 'test%' и для каждой соответствующей базы данных – сканирования каталога базы данных для определения соответствующих имён таблиц для шаблона 't%':
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test%' AND TABLE_NAME LIKE 't%';
2) Составление запросов, минимизирующих количество открываемых файлов таблиц
Для запросов, которые ссылаются на определённые столбцы таблиц INFORMATION_SCHEMA, доступно несколько оптимизаций, которые минимизируют количество открываемых файлов таблиц. Пример:
SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test';
В этом случае, после того как сервер отсканировал каталог базы данных для определения имён таблиц в базе данных, эти имена становятся доступными без дополнительных поисков в файловой системе. Таким образом, TABLE_NAME не требует открытия файлов. Значение ENGINE (движок хранения) можно определить, открыв файл .frm таблицы, не затрагивая другие файлы таблиц, такие как .MYD или .MYI файл.
Некоторые значения, такие как INDEX_LENGTH для таблиц MyISAM, требуют открытия файла .MYD или .MYI также.
Типы оптимизации открытия файлов обозначаются следующим образом:
SKIP_OPEN_TABLE: Файлы таблиц не нужно открывать. Информация уже стала доступна в запросе путем сканирования каталога базы данных.OPEN_FRM_ONLY: Необходимо открыть только файл.frmтаблицы.OPEN_TRIGGER_ONLY: Необходимо открыть только файл.TRGтаблицы.OPEN_FULL_TABLE: Поиск информации без оптимизации. Файлы.frm,.MYDи.MYIдолжны быть открыты.
Следующий список показывает, как указанные выше типы оптимизации применяются к столбцам таблиц INFORMATION_SCHEMA. Для таблиц и столбцов, не имеющих имени, ни одна из оптимизаций не применяется.
COLUMNS:OPEN_FRM_ONLYотносится ко всем столбцамKEY_COLUMN_USAGE:OPEN_FULL_TABLEотносится ко всем столбцамPARTITIONS:OPEN_FULL_TABLEотносится ко всем столбцамREFERENTIAL_CONSTRAINTS:OPEN_FULL_TABLEотносится ко всем столбцам-
Столбец Тип оптимизации TABLE_CATALOGOPEN_FRM_ONLYTABLE_SCHEMAOPEN_FRM_ONLYTABLE_NAMEOPEN_FRM_ONLYNON_UNIQUEOPEN_FRM_ONLYINDEX_SCHEMAOPEN_FRM_ONLYINDEX_NAMEOPEN_FRM_ONLYSEQ_IN_INDEXOPEN_FRM_ONLYCOLUMN_NAMEOPEN_FRM_ONLYCOLLATIONOPEN_FRM_ONLYCARDINALITYOPEN_FULL_TABLESUB_PARTOPEN_FRM_ONLYPACKEDOPEN_FRM_ONLYNULLABLEOPEN_FRM_ONLYINDEX_TYPEOPEN_FULL_TABLECOMMENTOPEN_FRM_ONLY -
Столбец Тип оптимизации TABLE_CATALOGSKIP_OPEN_TABLETABLE_SCHEMASKIP_OPEN_TABLETABLE_NAMESKIP_OPEN_TABLETABLE_TYPEOPEN_FRM_ONLYENGINEOPEN_FRM_ONLYVERSIONOPEN_FRM_ONLYROW_FORMATOPEN_FULL_TABLETABLE_ROWSOPEN_FULL_TABLEAVG_ROW_LENGTHOPEN_FULL_TABLEDATA_LENGTHOPEN_FULL_TABLEMAX_DATA_LENGTHOPEN_FULL_TABLEINDEX_LENGTHOPEN_FULL_TABLEDATA_FREEOPEN_FULL_TABLEAUTO_INCREMENTOPEN_FULL_TABLECREATE_TIMEOPEN_FULL_TABLEUPDATE_TIMEOPEN_FULL_TABLECHECK_TIMEOPEN_FULL_TABLETABLE_COLLATIONOPEN_FRM_ONLYCHECKSUMOPEN_FULL_TABLECREATE_OPTIONSOPEN_FRM_ONLYTABLE_COMMENTOPEN_FRM_ONLY TABLE_CONSTRAINTS:OPEN_FULL_TABLEотносится ко всем столбцамTRIGGERS:OPEN_TRIGGER_ONLYотносится ко всем столбцам-
Столбец Тип оптимизации TABLE_CATALOGOPEN_FRM_ONLYTABLE_SCHEMAOPEN_FRM_ONLYTABLE_NAMEOPEN_FRM_ONLYVIEW_DEFINITIONOPEN_FRM_ONLYCHECK_OPTIONOPEN_FRM_ONLYIS_UPDATABLEOPEN_FULL_TABLEDEFINEROPEN_FRM_ONLYSECURITY_TYPEOPEN_FRM_ONLYCHARACTER_SET_CLIENTOPEN_FRM_ONLYCOLLATION_CONNECTIONOPEN_FRM_ONLY
3) Используйте EXPLAIN, чтобы определить, может ли сервер использовать INFORMATION_SCHEMA оптимизации для запроса
Это особенно важно для INFORMATION_SCHEMA запросов, которые ищут информацию из нескольких баз данных, что может занять много времени и повлиять на производительность. Значение Extra в выводе EXPLAIN указывает, какие из описанных ранее оптимизаций сервер может использовать для оценки INFORMATION_SCHEMA запросов. Примеры ниже демонстрируют, какой тип информации можно ожидать в значении Extra.
mysql> EXPLAIN SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE
TABLE_SCHEMA = 'test' AND TABLE_NAME = 'v1'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: VIEWS
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
Использование постоянных значений поиска баз данных и таблиц позволяет серверу избежать сканирования каталогов. Для ссылок на VIEWS.TABLE_NAME необходимо открыть только файл .frm.
mysql> EXPLAIN SELECT TABLE_NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.TABLES\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: TABLES
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra: Open_full_table; Scanned all databases
Значения поиска не предоставлены (нет WHERE-запроса), поэтому сервер должен сканировать каталог данных и каждый каталог базы данных. Для каждой таким образом определенной таблицы выбирается имя таблицы и формат строки. TABLE_NAME не требует открытия дополнительных файлов таблиц (применяется оптимизация SKIP_OPEN_TABLE). ROW_FORMAT требует открытия всех файлов таблиц (применяется OPEN_FULL_TABLE). EXPLAIN сообщает OPEN_FULL_TABLE, потому что это дороже, чем SKIP_OPEN_TABLE.
mysql> EXPLAIN SELECT TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: TABLES
type: ALL
possible_keys: NULL
key: TABLE_SCHEMA
key_len: NULL
ref: NULL
rows: NULL
Extra: Using where; Open_frm_only; Scanned 1 database
Значение поиска имени таблицы не предоставлено, поэтому сервер должен просканировать каталог базы данных test. Для столбцов TABLE_NAME и TABLE_TYPE соответственно применяются оптимизации SKIP_OPEN_TABLE и OPEN_FRM_ONLY. EXPLAIN сообщает об этом, так как это дороже.
mysql> 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 = A.TABLE_NAME\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: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra: Using where; Open_frm_only; Scanned all databases;
Using join buffer
Для первой строки вывода EXPLAIN: Постоянные значения поиска базы данных и таблиц позволяют серверу избежать сканирования каталога для значений TABLES. Ссылки на TABLES.TABLE_NAME не требуют дополнительных файлов таблиц.
Для второй строки вывода EXPLAIN: Все значения таблицы COLUMNS являются OPEN_FRM_ONLY поисками, поэтому COLUMNS.TABLE_NAME требует открытия файла .frm.
mysql> EXPLAIN SELECT * FROM INFORMATION_SCHEMA.COLLATIONS\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: COLLATIONS
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra:
В этом случае оптимизации не применяются, потому что COLLATIONS не является одной из таблиц INFORMATION_SCHEMA, для которых доступны оптимизации.
© 2025 Oracle
Licensed under the GPLv2 License.