Spec-Zone.ru › MySQL 5.7

14.8.11.1 Настройка параметров постоянных статистических данных оптимизатора

  • 14.8.11.1.1 Настройка автоматического расчета статистики для постоянных статистических данных оптимизатора
  • 14.8.11.1.2 Настройка параметров статистики оптимизатора для отдельных таблиц
  • 14.8.11.1.3 Настройка количества выборочных страниц для статистики оптимизатора InnoDB
  • 14.8.11.1.4 Включение удаленных записей в расчет постоянной статистики
  • 14.8.11.1.5 Таблицы постоянной статистики InnoDB
  • 14.8.11.1.6 Пример таблиц постоянной статистики InnoDB
  • 14.8.11.1.7 Получение размера индекса с помощью таблицы innodb_index_stats

Функция постоянной статистики оптимизатора улучшает производительность, сохраняя статистику на диск и делая ее постоянной при перезапуске сервера, что повышает вероятность того, что будет принимать согласованные решения каждый раз для заданного запроса.

Статистика оптимизатора сохраняется на диск, когда innodb_stats_persistent=ON или когда отдельные таблицы определяются с помощью STATS_PERSISTENT=1. innodb_stats_persistent включен по умолчанию.

Ранее статистика оптимизатора очищалась при перезапуске сервера и после некоторых других типов операций, и пересчитывалась при следующем доступе к таблице. В результате при перерасчете статистики могли быть получены разные оценки, что приводило к разным решениям в планах выполнения запросов и вариациям производительности запросов.

Постоянная статистика хранится в таблицах mysql.innodb_table_stats и mysql.innodb_index_stats. См. Раздел 14.8.11.1.5, «Таблицы постоянной статистики InnoDB».

Если вы предпочитаете не сохранять статистику оптимизатора на диск, см. Раздел 14.8.11.2, «Настройка параметров статистики оптимизатора без сохранения на диск»

14.8.11.1.1 Настройка автоматического расчета статистики для постоянных статистических данных оптимизатора

Переменная innodb_stats_auto_recalc, которая включена по умолчанию, управляет тем, рассчитывается ли статистика автоматически, когда таблица претерпевает изменения более чем в 10% строк. Вы также можете настроить автоматический перерасчет статистики для отдельных таблиц, указав предложение STATS_AUTO_RECALC при создании или изменении таблицы.

Из-за асинхронного характера автоматического перерасчета статистики, происходящего в фоновом режиме, статистика может не пересчитываться мгновенно после выполнения операции DML, затрагивающей более 10% таблицы, даже если innodb_stats_auto_recalc включен. Перерасчет статистики может в некоторых случаях задерживаться на несколько секунд. Если актуальная статистика требуется немедленно, выполните ANALYZE TABLE, чтобы инициировать синхронный (фоновый) перерасчет статистики.

Если innodb_stats_auto_recalc отключен, вы можете гарантировать точность статистики оптимизатора, выполнив оператор ANALYZE TABLE после существенных изменений индексированных столбцов. Вы также можете рассмотреть добавление ANALYZE TABLE в скрипты настройки, которые вы выполняете после загрузки данных, и выполнение ANALYZE TABLE по расписанию в моменты низкой активности.

Когда к существующей таблице добавляется индекс или добавляется или удаляется столбец, статистика индекса рассчитывается и добавляется в таблицу innodb_index_stats независимо от значения innodb_stats_auto_recalc.

14.8.11.1.2 Настройка параметров статистики оптимизатора для отдельных таблиц

innodb_stats_persistent, innodb_stats_auto_recalc и innodb_stats_persistent_sample_pages - это глобальные переменные. Для переопределения этих параметров системы и настройки параметров статистики оптимизатора для отдельных таблиц можно определить предложения STATS_PERSISTENT, STATS_AUTO_RECALC и STATS_SAMPLE_PAGES в операторах CREATE TABLE или ALTER TABLE.

  • STATS_PERSISTENT указывает, следует ли включать для таблицы InnoDB. Значение DEFAULT задает параметр постоянной статистики таблицы в соответствии с значением innodb_stats_persistent. Значение 1 включает постоянную статистику для таблицы, а значение 0 отключает эту функцию. После включения постоянной статистики для отдельной таблицы используйте ANALYZE TABLE для расчета статистики после загрузки данных в таблицу.

  • STATS_AUTO_RECALC указывает, следует ли автоматически пересчитывать . Значение DEFAULT задает параметр перерасчета статистики таблицы в соответствии с значением innodb_stats_auto_recalc. Значение 1 вызывает перерасчет статистики, когда 10% данных таблицы изменены. Значение 0 предотвращает автоматический перерасчет для таблицы. При использовании значения 0 используйте ANALYZE TABLE для перерасчета статистики после существенных изменений в таблице.

  • STATS_SAMPLE_PAGES указывает количество страниц индекса, которое следует взять для выборки, когда кардинальность и другие статистические данные рассчитываются для индексированного столбца, например, при выполнении операции ANALYZE TABLE.

Все три предложения указаны в следующем примере CREATE TABLE:

CREATE TABLE `t1` (
`id` int(8) NOT NULL auto_increment,
`data` varchar(255),
`date` datetime,
PRIMARY KEY  (`id`),
INDEX `DATE_IX` (`date`)
) ENGINE=InnoDB,
  STATS_PERSISTENT=1,
  STATS_AUTO_RECALC=1,
  STATS_SAMPLE_PAGES=25;
14.8.11.1.3 Настройка количества выборочных страниц для статистики оптимизатора InnoDB

Оптимизатор использует оценку распределения ключей для выбора индексов в плане выполнения, основываясь на относительной важности индекса. Такие операции, как ANALYZE TABLE, приводят к тому, что InnoDB берёт выборку случайных страниц из каждого индекса таблицы для оценки важности индекса. Этот метод выборки называется .

Параметр innodb_stats_persistent_sample_pages контролирует количество выборочных страниц. Можно изменить это значение во время работы для управления качеством оценок статистики, используемых оптимизатором. Значение по умолчанию равно 20. Рассмотрите возможность изменения этого значения при возникновении следующих проблем:

  1. Статистика недостаточно точна, и оптимизатор выбирает не оптимальный план, как показано в выводе EXPLAIN. Можно проверить точность статистики, сравнив фактическую мощность индекса (определённую путём выполнения SELECT DISTINCT по столбцам индекса) с оценками в таблице mysql.innodb_index_stats.

    Если установлено, что статистика недостаточно точна, значение innodb_stats_persistent_sample_pages следует увеличить до тех пор, пока оценки статистики не станут достаточно точными. Однако слишком большое увеличение innodb_stats_persistent_sample_pages может привести к замедлению выполнения ANALYZE TABLE.

  2. Выполнение ANALYZE TABLE слишком долго. В этом случае innodb_stats_persistent_sample_pages следует уменьшить до тех пор, пока время выполнения ANALYZE TABLE станет приемлемым. Однако слишком большое уменьшение значения может привести к первой проблеме – неточным статистическим данным и не оптимальным планам выполнения запросов.

    Если не удаётся достичь баланса между точной статистикой и временем выполнения ANALYZE TABLE, рассмотрите возможность уменьшения количества индексированных столбцов в таблице или ограничения количества партиций для уменьшения сложности ANALYZE TABLE. Количество столбцов в первичном ключе таблицы также важно учитывать, так как столбцы первичного ключа добавляются к каждому не уникальному индексу.

    Дополнительная информация приведена в Разделе 14.8.11.3, «Оценивание сложности ANALYZE TABLE для таблиц InnoDB».

14.8.11.1.4 Включение строк, помеченных как удаленные, в вычисления постоянной статистики

По умолчанию, InnoDB считывает данные, не подтверждённые, при расчёте статистики. В случае незавершенной транзакции, удаляющей строки из таблицы, строки, помеченные на удаление, исключаются при вычислении оценок строк и статистики индексов, что может привести к не оптимальным планам выполнения для других транзакций, работающих с таблицей одновременно с уровнем изоляции транзакции, отличным от READ UNCOMMITTED. Чтобы избежать этой ситуации, можно включить параметр innodb_stats_include_delete_marked для включения строк, помеченных на удаление, при расчёте постоянной статистики оптимизатора.

При включенном innodb_stats_include_delete_marked, ANALYZE TABLE учитывает строки, помеченные на удаление, при перерасчёте статистики.

innodb_stats_include_delete_marked - это глобальное значение, которое влияет на все InnoDB таблицы, и оно применимо только к постоянной статистике оптимизатора.

innodb_stats_include_delete_marked была введена в MySQL 5.7.16.

14.8.11.1.5 Таблицы постоянной статистики InnoDB

Функция постоянной статистики использует управляемые изнутри таблицы в базе данных mysql, называемые innodb_table_stats и innodb_index_stats. Эти таблицы создаются автоматически во всех процедурах установки, обновления и сборки из исходного кода.

Таблица 14.4 Столбцы таблицы innodb_table_stats

Таблица 14.4 Столбцы таблицы innodb_table_stats
Имя столбца Описание
database_name Имя базы данных
table_name Имя таблицы, имя раздела или имя подраздела
last_update Отметка времени, указывающая последний раз, когда строка была обновлена
n_rows Количество строк в таблице
clustered_index_size Размер первичного индекса в страницах
sum_of_other_index_sizes Общий размер других (не первичных) индексов в страницах

Таблица 14.5 Столбцы таблицы innodb_index_stats

Таблица 14.5 Столбцы таблицы innodb_index_stats
Имя столбца Описание
database_name Имя базы данных
table_name Имя таблицы, имя раздела или имя подраздела
index_name Имя индекса
last_update Отметка времени, указывающая последний раз, когда InnoDB обновил эту строку
stat_name Имя статистики, значение которой сообщается в столбце stat_value
stat_value Значение статистики, имя которой указано в столбце stat_name
sample_size Количество выборочных страниц для оценки, предоставленной в столбце stat_value
stat_description Описание статистики, имя которой указано в столбце stat_name

Таблицы innodb_table_stats и innodb_index_stats включают столбец last_update, показывающий, когда последняя обновлялась статистика индекса:

mysql> SELECT * FROM innodb_table_stats \G
*************************** 1. row ***************************
           database_name: sakila
              table_name: actor
             last_update: 2014-05-28 16:16:44
                  n_rows: 200
    clustered_index_size: 1
sum_of_other_index_sizes: 1
...
mysql> SELECT * FROM innodb_index_stats \G
*************************** 1. row ***************************
   database_name: sakila
      table_name: actor
      index_name: PRIMARY
     last_update: 2014-05-28 16:16:44
       stat_name: n_diff_pfx01
      stat_value: 200
     sample_size: 1
     ...

Таблицы innodb_table_stats и innodb_index_stats можно обновлять вручную, что позволяет принудительно задавать определённый план оптимизации запроса или тестировать альтернативные планы без изменения базы данных. Если вы обновляете статистику вручную, используйте оператор FLUSH TABLE tbl_name для загрузки обновлённой статистики.

Постоянная статистика рассматривается как локальная информация, поскольку она относится к экземпляру сервера. Следовательно, таблицы innodb_table_stats и innodb_index_stats не реплицируются при автоматическом перерасчёте статистики. Если вы запускаете ANALYZE TABLE для инициирования синхронного перерасчёта статистики, этот оператор реплицируется (если вы не отключили для него логирование), и перерасчёт выполняется на репликах.

14.8.11.1.6 Пример таблиц постоянной статистики InnoDB

Таблица innodb_table_stats содержит одну строку для каждой таблицы. В следующем примере показан тип собираемых данных.

Таблица t1 содержит первичный индекс (столбцы a, b), вторичный индекс (столбцы c, d) и уникальный индекс (столбцы e, f):

CREATE TABLE t1 (
a INT, b INT, c INT, d INT, e INT, f INT,
PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)
) ENGINE=INNODB;

После вставки пяти строк образцовых данных таблица t1 выглядит следующим образом:

mysql> SELECT * FROM t1;
+---+---+------+------+------+------+
| a | b | c    | d    | e    | f    |
+---+---+------+------+------+------+
| 1 | 1 |   10 |   11 |  100 |  101 |
| 1 | 2 |   10 |   11 |  200 |  102 |
| 1 | 3 |   10 |   11 |  100 |  103 |
| 1 | 4 |   10 |   12 |  200 |  104 |
| 1 | 5 |   10 |   12 |  100 |  105 |
+---+---+------+------+------+------+

Чтобы немедленно обновить статистику, запустите ANALYZE TABLE (если innodb_stats_auto_recalc включен, статистика обновляется автоматически в течение нескольких секунд, при условии, что достигнут 10%-й порог для измененных строк таблицы):

mysql> ANALYZE TABLE t1;
+---------+---------+----------+----------+
| Table   | Op      | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.t1 | analyze | status   | OK       |
+---------+---------+----------+----------+

Статистика таблицы для таблицы t1 показывает, когда последний раз InnoDB обновлял статистику таблицы (2014-03-14 14:36:34), количество строк в таблице (5), размер кластеризованного индекса (1 страница) и комбинированный размер других индексов (2 страниц).

mysql> SELECT * FROM mysql.innodb_table_stats WHERE table_name like 't1'\G
*************************** 1. row ***************************
           database_name: test
              table_name: t1
             last_update: 2014-03-14 14:36:34
                  n_rows: 5
    clustered_index_size: 1
sum_of_other_index_sizes: 2

Таблица innodb_index_stats содержит несколько строк для каждого индекса. Каждая строка в таблице innodb_index_stats предоставляет данные, относящиеся к конкретной статистике индекса, которая указана в столбце stat_name и описана в столбце stat_description. Например:

mysql> SELECT index_name, stat_name, stat_value, stat_description
       FROM mysql.innodb_index_stats WHERE table_name like 't1';
+------------+--------------+------------+-----------------------------------+
| index_name | stat_name    | stat_value | stat_description                  |
+------------+--------------+------------+-----------------------------------+
| PRIMARY    | n_diff_pfx01 |          1 | a                                 |
| PRIMARY    | n_diff_pfx02 |          5 | a,b                               |
| PRIMARY    | n_leaf_pages |          1 | Number of leaf pages in the index |
| PRIMARY    | size         |          1 | Number of pages in the index      |
| i1         | n_diff_pfx01 |          1 | c                                 |
| i1         | n_diff_pfx02 |          2 | c,d                               |
| i1         | n_diff_pfx03 |          2 | c,d,a                             |
| i1         | n_diff_pfx04 |          5 | c,d,a,b                           |
| i1         | n_leaf_pages |          1 | Number of leaf pages in the index |
| i1         | size         |          1 | Number of pages in the index      |
| i2uniq     | n_diff_pfx01 |          2 | e                                 |
| i2uniq     | n_diff_pfx02 |          5 | e,f                               |
| i2uniq     | n_leaf_pages |          1 | Number of leaf pages in the index |
| i2uniq     | size         |          1 | Number of pages in the index      |
+------------+--------------+------------+-----------------------------------+

Столбец stat_name показывает следующие типы статистики:

  • size: Где stat_name=size, столбец stat_value отображает общее количество страниц в индексе.

  • n_leaf_pages: Где stat_name=n_leaf_pages, столбец stat_value отображает количество листовых страниц в индексе.

  • n_diff_pfxNN: Где stat_name=n_diff_pfx01, столбец stat_value отображает количество различных значений в первом столбце индекса. Где stat_name=n_diff_pfx02, столбец stat_value отображает количество различных значений в первых двух столбцах индекса и так далее. Где stat_name=n_diff_pfxNN, столбец stat_description показывает разделенный запятыми список столбцов индекса, которые учитываются.

Для дальнейшей иллюстрации статистики n_diff_pfxNN, которая предоставляет данные о мощности множества, рассмотрим еще раз пример таблицы t1, который был представлен ранее. Как показано ниже, таблица t1 создается с первичным индексом (столбцы a, b), вторичным индексом (столбцы c, d) и уникальным индексом (столбцы e, f):

CREATE TABLE t1 (
  a INT, b INT, c INT, d INT, e INT, f INT,
  PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)
) ENGINE=INNODB;

После вставки пяти строк образцовых данных таблица t1 выглядит следующим образом:

mysql> SELECT * FROM t1;
+---+---+------+------+------+------+
| a | b | c    | d    | e    | f    |
+---+---+------+------+------+------+
| 1 | 1 |   10 |   11 |  100 |  101 |
| 1 | 2 |   10 |   11 |  200 |  102 |
| 1 | 3 |   10 |   11 |  100 |  103 |
| 1 | 4 |   10 |   12 |  200 |  104 |
| 1 | 5 |   10 |   12 |  100 |  105 |
+---+---+------+------+------+------+

При запросе index_name, stat_name, stat_value и stat_description, где stat_name LIKE 'n_diff%', возвращается следующий результирующий набор:

mysql> SELECT index_name, stat_name, stat_value, stat_description
       FROM mysql.innodb_index_stats
       WHERE table_name like 't1' AND stat_name LIKE 'n_diff%';
+------------+--------------+------------+------------------+
| index_name | stat_name    | stat_value | stat_description |
+------------+--------------+------------+------------------+
| PRIMARY    | n_diff_pfx01 |          1 | a                |
| PRIMARY    | n_diff_pfx02 |          5 | a,b              |
| i1         | n_diff_pfx01 |          1 | c                |
| i1         | n_diff_pfx02 |          2 | c,d              |
| i1         | n_diff_pfx03 |          2 | c,d,a            |
| i1         | n_diff_pfx04 |          5 | c,d,a,b          |
| i2uniq     | n_diff_pfx01 |          2 | e                |
| i2uniq     | n_diff_pfx02 |          5 | e,f              |
+------------+--------------+------------+------------------+

Для индекса PRIMARY есть две строки n_diff%. Количество строк равно количеству столбцов в индексе.

Примечание

Для не уникальных индексов, InnoDB добавляет столбцы первичного ключа.

  • Где index_name=PRIMARY и stat_name=n_diff_pfx01, stat_value равен 1, что указывает на то, что в первом столбце индекса (столбец a) есть одно уникальное значение. Количество уникальных значений в столбце a подтверждается просмотром данных в столбце a в таблице t1, в котором есть одно уникальное значение (1). Подсчитанный столбец (a) показан в столбце stat_description результирующего набора.

  • Где index_name=PRIMARY и stat_name=n_diff_pfx02, stat_value равен 5, что указывает на то, что в двух столбцах индекса (a,b) есть пять уникальных значений. Количество уникальных значений в столбцах a и b подтверждается просмотром данных в столбцах a и b в таблице t1, в которых есть пять уникальных значений: (1,1), (1,2), (1,3), (1,4) и (1,5). Подсчитанные столбцы (a,b) показаны в столбце stat_description результирующего набора.

Для вторичного индекса (i1) есть четыре строки n_diff%. Для вторичного индекса определены только два столбца (c,d), но для вторичного индекса есть четыре строки n_diff%, потому что InnoDB добавляет суффикс ко всем не уникальным индексам с первичным ключом. В результате, вместо двух есть четыре строки n_diff%, чтобы учесть как столбцы вторичного индекса (c,d), так и столбцы первичного ключа (a,b).

  • Где index_name=i1 и stat_name=n_diff_pfx01, stat_value равен 1, что указывает на то, что в первом столбце индекса (столбец c) есть одно уникальное значение. Количество уникальных значений в столбце c подтверждается просмотром данных в столбце c в таблице t1, в котором есть одно уникальное значение: (10). Подсчитанный столбец (c) показан в столбце stat_description результирующего набора.

  • Где index_name=i1 и stat_name=n_diff_pfx02, stat_value равен 2, что указывает на то, что в первых двух столбцах индекса (c,d) есть два уникальных значения. Количество уникальных значений в столбцах c и d подтверждается просмотром данных в столбцах c и d в таблице t1, в которых есть два уникальных значения: (10,11) и (10,12). Подсчитанные столбцы (c,d) показаны в столбце stat_description результирующего набора.

  • Где index_name=i1 и stat_name=n_diff_pfx03, stat_value равен 2, что указывает на то, что в первых трех столбцах индекса (c,d,a) есть два уникальных значения. Количество уникальных значений в столбцах c, d и a подтверждается просмотром данных в столбцах c, d и a в таблице t1, в которых есть два уникальных значения: (10,11,1) и (10,12,1). Подсчитанные столбцы (c,d,a) показаны в столбце stat_description результирующего набора.

  • Где index_name=i1 и stat_name=n_diff_pfx04, stat_value равен 5, что указывает на то, что в четырех столбцах индекса (c,d,a,b) есть пять уникальных значений. Количество уникальных значений в столбцах c, d, a и b подтверждается просмотром данных в столбцах c, d, a и b в таблице t1, в которых есть пять уникальных значений: (10,11,1,1), (10,11,1,2), (10,11,1,3), (10,12,1,4) и (10,12,1,5). Подсчитанные столбцы (c,d,a,b) показаны в столбце stat_description результирующего набора.

Для уникального индекса (i2uniq) есть две строки n_diff%.

  • Где index_name=i2uniq и stat_name=n_diff_pfx01, значение stat_value равно 2, что указывает на два различных значения в первом столбце индекса (столбец e). Количество различных значений в столбце e подтверждается просмотром данных в столбце e в таблице t1, где есть два различных значения: (100) и (200). Подсчитанный столбец (e) отображается в столбце stat_description набора результатов.

  • Где index_name=i2uniq и stat_name=n_diff_pfx02, значение stat_value равно 5, что указывает на пять различных значений в двух столбцах индекса (e,f). Количество различных значений в столбцах e и f подтверждается просмотром данных в столбцах e и f в таблице t1, где есть пять различных значений: (100,101), (200,102), (100,103), (200,104) и (100,105). Подсчитанные столбцы (e,f) отображаются в столбце stat_description набора результатов.

14.8.11.1.7 Получение размера индекса с помощью таблицы innodb_index_stats

Вы можете получить размер индекса для таблиц, разделов или подразделов, используя таблицу innodb_index_stats. В приведенном ниже примере размеры индексов извлекаются для таблицы t1. Для определения таблицы t1 и соответствующей статистики индекса см. Раздел 14.8.11.1.6, «Пример таблиц постоянной статистики InnoDB».

mysql> SELECT SUM(stat_value) pages, index_name,
       SUM(stat_value)*@@innodb_page_size size
       FROM mysql.innodb_index_stats WHERE table_name='t1'
       AND stat_name = 'size' GROUP BY index_name;
+-------+------------+-------+
| pages | index_name | size  |
+-------+------------+-------+
|     1 | PRIMARY    | 16384 |
|     1 | i1         | 16384 |
|     1 | i2uniq     | 16384 |
+-------+------------+-------+

Для разделов или подразделов вы можете использовать тот же запрос с изменённым фрагментом WHERE для получения размеров индексов. Например, следующий запрос извлекает размеры индексов для разделов таблицы t1:

mysql> SELECT SUM(stat_value) pages, index_name,
       SUM(stat_value)*@@innodb_page_size size
       FROM mysql.innodb_index_stats WHERE table_name like 't1#P%'
       AND stat_name = 'size' GROUP BY index_name;

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/innodb-persistent-stats.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API