Как InnoDB вычисляет table_rows для information_schema?

Фон

Итак, я понимаю, что для таблиц InnoDB table_rows из information_schema является лишь приблизительной оценкой, и что подсчет точного количества строк нетривиален из-за транзакций.

Но у меня есть некоторые таблицы, для которых table_rows находится в пределах нескольких % от истинного количества, и некоторые таблицы, подобные этой:

mysql> SELECT table_rows FROM information_schema.tables WHERE table_name="__unit_previews";
+------------+
| table_rows |
+------------+
|  226992266 |
+------------+
1 row in set (0.03 sec)

mysql> SELECT COUNT(*) FROM __unit_previews;
+----------+
| COUNT(*) |
+----------+
|   144156 |
+----------+
1 row in set (0.14 sec)

Я думаю, вы должны быть очень великодушны, чтобы назвать это приблизительной оценкой.

Открытых сделок нет; Я не удалял тайно несколько сотен миллионов строк; Я запустил analyze table, чтобы убедиться, что информационная схема актуальна.

Я использую MySQL 5.6.13 (@@innodb_version также говорит 5.6.13), и в этой таблице есть row_format=dynamic с примерно 400 КБ атрибутов больших двоичных объектов на строку. information_schema также сообщает, что data_length — это 58020446208, а avg_row_length — это 255.

Вопросы

Так как же InnoDB вычисляет table_rows для information_schema.tables?

Возможно, связано: как он определяет data_length и avg_row_length? Включает ли это внешнее хранилище больших двоичных объектов (т. е. за пределами страницы B-дерева, но по-прежнему управляемое InnoDB)?

Если table_rows используется в оптимизации SQL, должен ли я беспокоиться о том, что он отключен на 3 порядка?

Есть ли лучший способ оценить количество строк по атрибутам, доступным в information_schema?


person KQS    schedule 04.02.2016    source источник
comment
Отказ от ответственности: я понятия не имею, как ответить на ваши вопросы, но я знаю одно: вы не можете полагаться на information_schema для размера данных или количества строк. Всегда. Я использую простой триггер, который увеличивает/уменьшает счетчик для конкретной таблицы, число строк которой мне нужно знать. Кроме этого подхода, я не нашел ничего лучше. Что касается размера данных, выделенная и потраченная сумма никогда не бывает одинаковой. Таким образом, я просто прошу свою ОС сообщить мне размер на диске. К сожалению, это не отвечает на ваши вопросы, но пока кто-то более знающий не прыгнет .. :)   -  person N.B.    schedule 05.02.2016


Ответы (1)


То, что вы сделали DELETE, оказало влияние.

InnoDB точно знает, какое значение имеет Data_length. Судя по зондам (8 в старых версиях), он имеет некоторое ощущение (конечно, очень плохое) для распределения материала. Думаю, он получает оценку Avg_row_length, а затем делится, чтобы получить table_rows.

Запустите ANALYZE еще раз; первое число останется прежним; два других изменятся.

Поля TEXT и BLOB (и т. д.) хранятся во внеблочном хранилище по-разному, в зависимости от ROW_FORMAT. Это добавляет путаницы и расчетов.

Более новые версии (начиная с 5.6.6?) работают немного лучше.

Ошибка в 1000 раз очень плоха. Я редко вижу больше, чем коэффициент 2 (в любом направлении).

Я только что попробовал одну из своих таблиц, похожую на вашу, и получил коэффициент 7. Хе-хе - ANALYZE сделал подсчет строк более далеким от истины. OPTIMIZE стало лучше, но все равно в 5 раз меньше. Ну что ж.

Предлагаем опубликовать сообщение об ошибке на http://bugs.mysql.com.

person Rick James    schedule 06.02.2016
comment
Извините за недоразумение - я пытался сказать, что не делал DELETE (на самом деле эта таблица почти никогда не удаляется и не обновляется). Я подозреваю, что вы правы в том, что он делит data_length на avg_row_length, и что проблема возникает из-за того, как подсчитывается внеблочная память — кажется, что она включена в data_length, но не включена в оценку avg_row_length. Я посмотрю насчет публикации отчета об ошибке. - person KQS; 06.02.2016