Почему SHOW TABLE STATUS innodb так ненадежен? - PullRequest
15 голосов
/ 24 декабря 2011

Я знаю, что вы не должны полагаться на значения, возвращаемые SHOW TABLE STATUS InnoDB. В частности, количество строк и средняя длина данных.

Но я подумал, что, возможно, в какой-то момент это было точное значение, а затем innodb обновляет его только во время таблицы ANALYZE или, возможно, какого-то другого нечастого события.

Вместо этого я вижу, что я могу запускать SHOW TABLE STATUS для одной и той же таблицы 5 раз за 5 секунд и просто каждый раз получать совершенно разные числа (несмотря на то, что в таблице нет операций вставки / удаления между ними)

Откуда эти значения на самом деле? Они просто испорчены в innodb?

Ответы [ 2 ]

23 голосов
/ 24 декабря 2011

Официальная документация MySQL 5.1 признает, что InnoDB не дает точной статистики с SHOW TABLE STATUS. В то время как таблицы MYISAM специально хранят внутренний кеш метаданных, таких как количество строк и т. Д., Механизм InnoDB хранит как данные таблицы, так и индексы в * / var / lib / mysql / ibdata **

InnoDB не имеет подходящего индексного файла, позволяющего быстро запрашивать номера строк.

Несовместимые номера строк таблицы сообщаются SHOW TABLE STATUS, потому что InnoDB динамически оценивает значение 'Rows', выбирая диапазон данных таблицы (в * / var / lib / mysql / ibdata **), а затем экстраполирует приблизительное число рядов. Настолько, что документация InnoDB признает неточность номера строки до 50% при использовании SHOW TABLE STATUS

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

Сначала убедитесь, что кэширование запросов включено:

mysql> SHOW VARIABLES LIKE 'have_query_cache';

Если значение have_query_cache равно NO , включите кэш запросов, добавив следующие строки в / etc / my.cnf , а затем перезапустите mysqld.

have_query_cache=1    # added 2017 08 24 wh
query_cache_size  = 1048576
query_cache_type  = 1
query_cache_limit = 1048576

(подробнее см. http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)

Запрос содержимого кеша с помощью

mysql> SHOW STATUS LIKE 'Qcache%';

Теперь используйте оператор SQL_CALC_FOUND_ROWS в запросе SELECT:

SELECT SQL_CALC_FOUND_ROWS COUNT(*) FROM my_innodb_table

SQL_CALC_FOUND_ROWS попытается выполнить чтение из кэша и, если этот запрос не будет найден, выполнить запрос к указанной таблице, а затем зафиксировать количество строк таблицы в кэше запросов. Дополнительные выполнения вышеупомянутого запроса (или других «кэшируемых» операторов SELECT - см. Ниже) будут обращаться к кэшу и возвращать правильный результат.

Последующие 'cachable' SELECT запросы - даже если они LIMIT результат - будут обращаться к кешу запросов и позволят вам получить (только один раз) общее количество строк таблицы с помощью

SELECT FOUND_ROWS();

, который возвращает правильный итог строки таблицы предыдущего кэшированного запроса.

4 голосов
/ 24 декабря 2011

Причинами отсутствия точной статистики, в том числе количества строк в таблице, является многовариантность строк, используемая InnoDB для предоставления транзакций. Фактическое количество строк зависит от уровня изоляции транзакций (поскольку незафиксированные транзакции могли удалять или вставлять записи), и разные транзакции могут выполняться на разных уровнях изоляции, что означает, что вопрос «сколько существует записей 'можно ответить правильно, только если не запущены транзакции. Так что ведение счетчика строк или длины данных практически невозможно.

Подробнее о Ограничения InnoDB

...