LogNotes

2025-06-03 17:52:15
generator mysql
Для создания таблицы в MariaDB и генерации данных объемом около 10 ГБ, я предложу структуру таблицы, SQL-скрипт для ее создания и метод генерации данных с использованием хранимой процедуры. Учитывая, что вы используете Galera Cluster, я учту особенности репликации и предложу решение, которое минимизирует влияние на кластер. Предполагается, что вы хотите создать таблицу с данными для тестирования, и я выберу универсальную структуру таблицы, которая может быть адаптирована под ваши нужды.

---

### 1. **Структура таблицы**
Создадим таблицу `test_data` с несколькими полями, чтобы объем данных приблизился к 10 ГБ. Для этого можно использовать поля разных типов, включая текстовые и числовые. Пример таблицы:

```sql
CREATE TABLE test_data (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id INT UNSIGNED NOT NULL,
    transaction_date DATETIME NOT NULL,
    amount DECIMAL(15,2) NOT NULL,
    description VARCHAR(255) NOT NULL,
    data_blob TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_transaction_date (transaction_date)
) ENGINE=InnoDB;
```

- **`id`**: Уникальный идентификатор записи.
- **`user_id`**: Числовое поле для идентификатора пользователя.
- **`transaction_date`**: Дата транзакции.
- **`amount`**: Числовое поле для суммы.
- **`description`**: Текстовое поле для описания.
- **`data_blob`**: Поле для хранения больших текстовых данных, чтобы увеличить объем.
- **`created_at`**: Метка времени создания.
- **Индексы**: Добавлены для реалистичности и производительности запросов.
- **InnoDB**: Используется, так как это стандартный движок для Galera Cluster.

---

### 2. **Оценка размера данных**
Чтобы достичь 10 ГБ, предположим, что каждая запись занимает около 1 КБ (включая `TEXT`, `VARCHAR` и индексы). Тогда потребуется около **10 миллионов записей** (10 ГБ / 1 КБ = ~10,000,000 строк). Размер записи зависит от данных в `data_blob` и индексов, поэтому мы можем варьировать длину текста в `data_blob` для точной настройки.

---

### 3. **Хранимая процедура для генерации данных**
Для генерации данных создадим хранимую процедуру, которая будет вставлять записи в таблицу. Процедура будет генерировать случайные данные с использованием встроенных функций MariaDB.

```sql
DELIMITER //

CREATE PROCEDURE generate_test_data(IN num_rows BIGINT)
BEGIN
    DECLARE i BIGINT DEFAULT 0;
    DECLARE batch_size INT DEFAULT 1000;
    DECLARE random_text VARCHAR(1000);

    WHILE i < num_rows DO
        -- Начинаем транзакцию для вставки пакета
        START TRANSACTION;
        
        -- Вставляем batch_size записей
        INSERT INTO test_data (user_id, transaction_date, amount, description, data_blob)
        SELECT
            FLOOR(RAND() * 1000000) + 1 AS user_id,
            NOW() - INTERVAL FLOOR(RAND() * 365 * 5) DAY AS transaction_date,
            ROUND(RAND() * 10000, 2) AS amount,
            CONCAT('Transaction #', FLOOR(RAND() * 1000000)) AS description,
            REPEAT(CONCAT('Sample data ', FLOOR(RAND() * 1000), ' '), 50) AS data_blob
        FROM
            (SELECT a.N + b.N * 10 + c.N * 100 + 1 AS n
             FROM
                (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
                (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b,
                (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c
             WHERE a.N + b.N * 10 + c.N * 100 < batch_size
            ) numbers
        LIMIT batch_size;

        -- Фиксируем транзакцию
        COMMIT;

        -- Увеличиваем счетчик
        SET i = i + batch_size;
    END WHILE;
END //

DELIMITER ;
```

---

### 4. **Запуск генерации данных**
Чтобы сгенерировать около 10 миллионов записей:
```sql
CALL generate_test_data(10000000);
```

- **batch_size=1000**: Данные вставляются пакетами по 1000 записей, чтобы минимизировать нагрузку на кластер и избежать блокировки.
- **`data_blob`**: Поле заполняется повторяющимся текстом длиной ~500–1000 байт, чтобы увеличить размер записи.
- **Транзакции**: Использование `START TRANSACTION` и `COMMIT` снижает влияние на репликацию в Galera Cluster, так как данные синхронизируются пакетами.

---

### 5. **Особенности для Galera Cluster**
- **Репликация**: В Galera Cluster каждая транзакция реплицируется на все узлы. Чтобы избежать перегрузки:
  - Используйте небольшие пакеты (batch_size=1000 в процедуре).
  - Мониторьте состояние кластера во время генерации:
    ```sql
    SHOW STATUS LIKE 'wsrep_local_state_comment';
    ```
    Убедитесь, что все узлы остаются в состоянии `Synced`.
- **Память**: Убедитесь, что `innodb_buffer_pool_size` на каждом узле настроен так, чтобы выдерживать нагрузку (например, 13 ГБ для 16 ГБ RAM, как обсуждалось ранее).
- **Логи транзакций**: Убедитесь, что параметр `innodb_log_file_size` достаточно большой (например, 512M–1G), чтобы избежать узких мест при записи:
  ```ini
  [mysqld]
  innodb_log_file_size=512M
  ```
  Примените это на всех узлах и перезапустите их по одному.

---

### 6. **Проверка размера таблицы**
После генерации данных проверьте размер таблицы:
```sql
SELECT
    table_name,
    ROUND((data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM
    information_schema.tables
WHERE
    table_schema = 'your_database_name'
    AND table_name = 'test_data';
```

Если размер меньше или больше 10 ГБ, можно:
- Увеличить/уменьшить длину `data_blob` в процедуре (измените `REPEAT(..., 50)` на большее/меньшее значение).
- Изменить количество записей в `generate_test_data`.

---

### 7. **Оптимизация и мониторинг**
- **Мониторинг кластера**: Во время генерации следите за параметрами `wsrep_flow_control_paused` и `wsrep_local_recv_queue`:
  ```sql
  SHOW STATUS LIKE 'wsrep_flow_control_paused';
  SHOW STATUS LIKE 'wsrep_local_recv_queue';
  ```
  Если значения растут, уменьшите `batch_size` в процедуре.
- **Потребление памяти**: Проверьте, что MariaDB на каждом узле не превышает 80% RAM:
  ```bash
  free -m
  top
  ```
- **Резервное копирование**: Перед генерацией данных создайте резервную копию конфигурации и данных кластера.

---

### 8. **Примечания**
- **Время выполнения**: Генерация 10 ГБ данных может занять значительное время (от десятков минут до часов) в зависимости от производительности серверов и настроек кластера.
- **Galera Cluster**: Выполняйте генерацию на одном узле, так как данные автоматически реплицируются на остальные узлы.
- **Тестирование**: Если это тестовая операция, выполняйте на staging-окружении, чтобы не повлиять на продакшен.
- **Очистка**: Если таблица создается для тестов, вы можете удалить ее после использования:
  ```sql
  DROP TABLE test_data;
  ```

---

### 9. **Альтернативы**
Если хранимая процедура работает слишком медленно, можно:
- Использовать утилиту `mysqlslap` для генерации тестовых данных.
- Создать CSV-файл с данными (например, с помощью Python) и импортировать его:
  ```bash
  mysqlimport --local --fields-terminated-by=',' --lines-terminated-by='\n' your_database_name test_data.csv
  ```

---

Если вам нужна другая структура таблицы или дополнительные параметры (например, конкретные типы данных или распределение), уточните, и я адаптирую решение. Сообщите, если возникнут проблемы при создании таблицы или генерации данных!
← Previous Next →
Back to list