Определение количества строк MySQL для DELETE для достижения целевого размера базы данных - PullRequest
0 голосов
/ 20 октября 2018

У меня есть база данных с 3 таблицами (A, B, C), которые мне нужно поддерживать ниже определенного порогового размера.

A имеет отношение 1-ко-многим с B и C ...

В частности, A, B и C имеют столбец g_id, который используется для установления отношениядруг с другом .. Вроде как графическая структура, где A, B и C - это графы, узлы и ребра соответственно.

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

Я попытался сделать следующее:

  1. Выбрать размербаза данных с

     SELECT
         TABLE_NAME,
         round(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) as SIZE_MB
          FROM
              information_schema.TABLES
          WHERE
              TABLE_NAME in ('A', 'B', 'C') AND
              TABLE_SCHEMA = DATABASE()
          ORDER BY
              SIZE_MB DESC
    
  2. Попытка оценить размеры каждой логической группировки (A, B, C) относительно их g_ids ...

    SELECT
        g_id,
        SUM(length(col1)) + SUM(constant) as total
    FROM (
        (SELECT A.g_id, A.col1, 22 as constant FROM A) UNION ALL
        (SELECT B.g_id, B.col1, 22 as constant FROM B) UNION ALL
        (SELECT C.g_id, C.col1, 22 as constant FROM C) UNION ALL
       ) ABC
    GROUP BY g_id
    ORDER BY g_id;
    

, где константа 22 - это всего лишь приблизительная оценка стоимости хранения некоторых фиксированных больших точек, временных отметок и т. Д. На строку ... а col1 - текстовое поле с переменной длиной.

После загрузки части 2 в память циклически перебирайте выбранные строки и программно добавляйте g_ids в список до тех пор, пока не будет выбрано достаточно строк для удаления, чтобы вернуть базу данных к нужному размеру.

Наконец выполните DELETE WHERE g_id IN ({g_ids}) для таблиц A, B, C ...

Проблема в том, чторазмер, возвращенный из части 1, похоже, повлек за собой некоторые накладные расходы.Например, когда я запускал часть 1, размер базы данных составлял около 3 ГБ, но когда я сложил все строки из части 2, это было только около 2 ГБ.И, кажется, нет предсказуемого расхождения в росте по мере роста таблицы.

Это несоответствие размера сообщило information_schema.TABLES, и мой оценочный запрос SUM заставляет меня удалить больше строк, чем мне действительно нужно.

Некоторые вопросы:

  1. AmЯ даже правильно подхожу к этой проблеме?
  2. Я не уверен в своих расчетах?
  3. Как определить накладные расходы?

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Измерение размера строки в InnoDB довольно грязное.Я считаю, что сложение размеров полей (8 для BIGINT и средней длины для VARCHAR и т. Д.), А затем умножение на 2 или 3 приблизится к пространству, необходимому для InnoDB.

Проще получить Avg_row_size от SHOW TABLE STATUS (или эквивалент в information_schema.Tables).

Циклическая обработка строк не будет более точной, если размеры строк не изменятся достаточнодико.Даже в этом случае «среднее» может быть таким же хорошим.

Да PARTITION BY RANGE(TO_DAYS(..)) - отличный способ ускорить удаление.Затем вы можете посмотреть размеры разделов, чтобы узнать, когда пришло время удалить самый старый раздел.Это, однако, предполагает, что вы хотите удалить «все строки до некоторой даты».Подробнее о таком разделении: http://mysql.rjweb.org/doc.php/partitionmaint

Вы говорите, что ваши данные настолько велики, что распределяются по нескольким серверам («огорожены»)?Пожалуйста, предоставьте больше деталей.Часто можно применять методы, позволяющие избежать такого быстрого взрыва данных.

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

0 голосов
/ 20 октября 2018

Я думаю, что вы используете неправильный подход, думая о удалении записей.Удаление записей - очень дорогая операция.

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

Затем вы можете «удалить» строки, удалив старые разделы.

...