Spec-Zone.ru › MySQL 8.4

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

  • 17.8.10.1.1 Настройка автоматического расчета статистики для постоянных статистических данных оптимизатора
  • 17.8.10.1.2 Настройка параметров статистики оптимизатора для отдельных таблиц
  • 17.8.10.1.3 Настройка количества анализируемых страниц для статистики оптимизатора InnoDB
  • 17.8.10.1.4 Включение записей, помеченных на удаление, в расчёты постоянной статистики
  • 17.8.10.1.5 Таблицы постоянной статистики InnoDB
  • 17.8.10.1.6 Пример таблиц постоянной статистики InnoDB
  • 17.8.10.1.7 Получение размера индекса с помощью таблицы innodb_index_stats

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

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

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

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

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

17.8.10.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.

Для гистограммы с включенной AUTO UPDATE (см. Анализ статистики гистограммы), автоматический перерасчет постоянной статистики также приводит к обновлению гистограммы.

17.8.10.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;
17.8.10.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. Также важно учитывать количество столбцов в первичном ключе таблицы, так как столбцы первичного ключа добавляются к каждому не уникальному индексу.

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

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

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

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

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

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

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

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

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

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

Таблица 17.7 Столбцы таблицы innodb_index_stats
Имя столбца Описание
database_name Имя базы данных
table_name Имя таблицы, раздела или подраздела
index_name Имя индекса
last_update Отметка времени, показывающая последний раз, когда строка была обновлена
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 для инициирования синхронного перерасчета статистики, оператор будет реплицирован (если вы не запретили журналирование для него), и перерасчет произойдет на репликах.

17.8.10.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 набора результатов.

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

Вы можете получить размер индекса для таблиц, разделов или подразделов, используя таблицу innodb_index_stats. В следующем примере размеры индексов извлекаются для таблицы t1. Определение таблицы t1 и соответствующих статистических данных индекса см. в Разделе 17.8.10.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-8.4-en/innodb-persistent-stats.html

Spec-Zone.ru

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