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

У меня есть таблица, которая вставляется и удаляется с высокой скоростью. Количество строк никогда не превышает нескольких сотен, и я бы не ожидал, что оно будет больше нескольких мегабайт, но размер таблицы составляет 20 гигабайт и продолжает расти. Он использует MySQL 5.6.35 и движок InnoDB. Я ожидал бы, что вставленные строки будут вставлены в пространство, оставленное удаленными строками, но, похоже, это не так. Он растет до этого уровня в течение недели, и в какой-то момент кажется, что какой-то фоновый процесс запускается и медленно уменьшает его на несколько гигабайт.

Проблема с такой большой таблицей заключается в том, что любые запросы, сканирующие всю таблицу, такие как count(*), выполняются очень медленно.

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

В будущем рассмотрите [эти методы] для больших удалений/обновлений.

Rick James 12.05.2019 06:20
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
1
1 075
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуйте OPTIMIZE TABLE на этой таблице.

OPTIMIZE TABLE reorganizes the physical storage of table data and associated index data, to reduce storage space and improve I/O efficiency when accessing the table. The exact changes made to each table depend on the storage engine used by that table.

https://dev.mysql.com/doc/refman/5.6/en/optimize-table.html

Ответ принят как подходящий

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

Например, прочитайте:

If you insert and delete rows in smallish batches at about the same rate in the table, the purge thread can start to lag behind and the table can grow bigger and bigger because of all the “dead” rows, making everything disk-bound and very slow. In such a case, throttle new row operations, and allocate more resources to the purge thread by tuning the innodb_max_purge_lag system variable. See Section 14.14, “InnoDB Startup Options and System Variables” for more information.

Я никогда не сталкивался ни с одним сайтом, который устанавливал innodb_max_purge_lag, потому что это означает, что их непрерывная запись в базу данных может иногда замедляться. Обычно они этого не хотят.

Вместо этого я установил innodb_purge_threads=4 вместо 1 по умолчанию. Это помогает очистке действовать быстро, когда она запускается.

Очистка еще больше задерживается, если ваше приложение держит транзакции открытыми, которым необходимо удерживать эти удаленные строки, чтобы удовлетворить их представление базы данных REPEATABLE-READ. Неважно, насколько быстро выполняется очистка или сколько потоков у вас есть для ее выполнения, если очистка предотвращается требованиями к моментальным снимкам открытых транзакций.

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

Помогут ли дополнительные потоки очистки, если это всего лишь одна таблица? Документация, казалось, предполагала обратное.

ubpsh 10.04.2019 19:25

Я не знаю точно, но я ожидаю, что это зависит от того, какие строки вы удалили, и насколько вероятно их перекрытие при работе потоков очистки.

Bill Karwin 10.04.2019 19:31

@BillKarwin Я также столкнулся с той же проблемой с большой таблицей innodb. Моя скорость удаления намного превышает скорость вставки, а строки, которые я удаляю, очень старые и не читаются/не обновляются ни в каких запросах. Тем не менее, размер данных и размер индекса растут.

CJ. 13.05.2020 09:19

@CJ. У вас может быть фрагментация таблицы, когда страницы и экстенты частично заполнены, но в основном пусты. Запуск OPTIMIZE TABLE (или любого другого ALTER TABLE, который копирует таблицу) должен дефрагментировать ее, скопировав таблицы в новое табличное пространство в дефрагментированном формате. Если вы не хотите, чтобы таблица была заблокирована, используйте pt-онлайн-схема-изменение.

Bill Karwin 13.05.2020 15:35

Другие вопросы по теме