CONCAT строка для использования longblog и диска mysql - PullRequest
0 голосов
/ 02 января 2019

Если я таблица innodb, этот запрос выполняется много раз (раз в секунду в течение некоторого времени с добавлением небольшого количества данных) и имеет innodb_files_per_table = 0, может ли это вызвать проблемы с хранилищем?Размер самого двоичного объекта может составлять 2-3 МБ, но я потерял 30 ГБ использования данных, и мне интересно, виноват ли этот код каким-либо образом или мне нужно искать что-то еще.

SQL

UPDATE phppos_app_files 
SET file_data = CONCAT(file_data, "NEW LINE OF DATA")
WHERE file_id = 10;

Схема:

mysql> show create table phppos_app_files;
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table            | Create Table                                                                                                                                                                                                                                                                                                                                                                                                             |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_app_files | CREATE TABLE `phppos_app_files` (
  `file_id` int(10) NOT NULL AUTO_INCREMENT,
  `file_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `file_data` longblob NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `expires` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`file_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7577 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> 

Данные, хранящиеся в столбце блога, составляют 2-3 МБ текста журнала;просто текст.Однако мой вопрос, который я задаю, заключается в том, что если частые запросы на обновление, когда вы используете текущее значение, приводят к проблемам с хранилищем, то есть к огромным проблемам с базой данных.Я просто хочу убедиться, что в нем хранится наименьшее количество информации, и если обновление с помощью concat может вызвать огромные проблемы с диском.

Ответы [ 3 ]

0 голосов
/ 02 января 2019

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

  • сжатие перед сохранением, как объяснено в этой документации (может иметь отношение к вашему случаю использования, так как ваш BLOB хранит текст)
  • периодически запускайте команду OPTIMIZE TABLE , чтобы реорганизовать физическое хранилище.Как прокомментировал Билл Карвин, с отключенной опцией innodb_file_per_table это не сократит табличное пространство.Однако он вернет пространство, потерянное из-за фрагментации, и пометит его как доступный в табличном пространстве: поэтому он будет повторно использовать любые пустые экстенты, прежде чем снова увеличит табличное пространство.
0 голосов
/ 02 января 2019

Если вы часто обновляете большие BLOB-объекты, он действительно может временно использовать много места и оставить фрагментированное табличное пространство.

Обновление копирует исходные страницы данных в «журнал отмен», который является просто областью страниц в табличном пространстве.InnoDB сохраняет эти скопированные страницы на случай, если вы откатите свою транзакцию и восстановите исходные данные.После того, как вы подтвердите свое обновление, копия в журнале отмены больше не нужна, и InnoDB будет постепенно очищаться.Но если ваши обновления, как вы говорите, частые, вы можете накапливать мусор в журнале отмены быстрее, чем InnoDB может его очистить.

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

Чтобы смягчить это, MySQL 5.6 ввел опцию, позволяющую сохранять журнал отмены за пределами системного табличного пространства, а MySQL 5.7 представил функцию обрезанияотменить журналы после того, как они убраны.Прочитайте https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-tablespaces.html для получения дополнительной информации об этих функциях.


Если вам интересна внутренняя структура файлов InnoDB, я рекомендую попробовать инструменты с открытым исходным кодом, которые написал Джереми Коул: https://github.com/jeremycole/innodb_ruby/wiki

Вы можете создавать различные сводки того, что находится в вашем табличном пространстве ibdata1.Большая часть файла может быть неиспользована, но все еще занимает место.

Вот пример из моей локальной песочницы MySQL.У меня есть только одна таблица с innondb_file_per_table=0 (все остальные таблицы находятся за пределами центрального табличного пространства).Я запустил эту команду:

innodb_space -s /usr/local/var/mysql/ibdata1 -T mydatabase/mytable space-extents-illustrate

Вот иллюстрация, которую он создал.Легенда (не входит в комплект) показала, что данные и индексы для одной моей таблицы попали на страницы между 3008 и 3392. Другими вещами были в основном системные структуры данных InnoDB (черные), системные таблицы, буферы вставок (темно-желтые) и незанятые.страницы (серый).

enter image description here

0 голосов
/ 02 января 2019

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

SELECT 
     table_schema as `Database`, 
     table_name AS `Table`, 
     round(((data_length + index_length) / 1024 / 1024), 2) `Size in MB` 
FROM information_schema.TABLES 
ORDER BY (data_length + index_length) DESC

действительно, общий объем используемого пространства остается неизменным.

Если вы используете innodb_files_per_table=0, у вас будет только одно табличное пространство, и поскольку ваши данные быстро изменяются, существуетвероятность того, что ваше табличное пространство будет фрагментировано во времени.

Если в будущем вы решите удалить или урезать вашу таблицу, размер вашего табличного пространства останется неизменным (не уменьшится), поэтому вы не сможете восстановить пространство после операции удаления.

...