Способно ли хранилище данных MySQL обрабатывать 10+ миллионов записей с 200 колонками?

Какая будет разница в скорости выполнения запроса и сколько памяти потребуется для его выполнения, если хранить метрики A, B, C в виде колонок или массива с числовыми значениями, и затем вычислять сумму каждой метрики? Например, если есть строки вида "ключевое слово 1 | site 1 | [5, 7, 9, ...]" и "ключевое слово 1 | site 2 | [1, 3, 2, ...]", как будет выглядеть запрос с группировкой по ключевому слову и подсчетом суммы каждой метрики, чтобы результат был в формате "ключевое слово 1 | [6, 10, 11, ...]"?
  • 24 января 2024 г. 13:49
Ответы на вопрос 3
### Обработка 10+ миллионов записей с 200 колонками

MySQL может обрабатывать 10+ миллионов записей с 200 колонками, но эффективность работы с таким объемом данных и размером таблицы будет зависеть от многих факторов, включая:

1. Аппаратное обеспечение сервера (CPU, ОЗУ, тип и скорость дисков)
2. Настройка MySQL (буферы, кэширование, индексы и т.д.)
3. Структура таблицы и типы данных колонок
4. Комплексность и оптимизация SQL-запросов
5. Стратегия разбиения данных (шардинг или партиционирование)

### Разница в скорости и потребление памяти

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

Хранение метрик в массивах может упростить модель данных, но обработка таких массивов обычно менее эффективна. Например, индексация таких данных осложнена, а операции над массивами могут потребовать больше времени и CPU.

### SQL Запрос

MySQL не поддерживает встроенный тип данных "массив", но вы можете использовать сериализацию данных в строку, такую как JSON. Предположим, у вас есть таблица с JSON-полем, содержащим массивы чисел:

```sql
CREATE TABLE metrics (
    keyword VARCHAR(255),
    site VARCHAR(255),
    data JSON
);
```

Вычисление суммы каждой метрики в группе по ключевому слову с использованием JSON-функций в MySQL могло бы выглядеть примерно так:

```sql
SELECT
    keyword,
    JSON_ARRAYAGG(sum_val) as sums
FROM (
    SELECT
        keyword,
        JSON_TABLE(
            data,
            "$[*]" COLUMNS(
                idx FOR ORDINALITY,
                val INT PATH "$"
            )
        ) as jt
    FROM metrics
) as data_table
JOIN (
    SELECT
        idx,
        SUM(val) as sum_val
    FROM (
        SELECT
            keyword,
            JSON_TABLE(
                data,
                "$[*]" COLUMNS(
                    idx FOR ORDINALITY,
                    val INT PATH "$"
                )
            ) as jt
        FROM metrics
    ) as s 
    GROUP BY idx
) as sums_table USING (idx)
GROUP BY keyword;
```

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

Также важно понимать, что в данном запросе мы предполагаем, что массивы в JSON одинаковой длины и элементы каждого массива должны быть сравнимы между собой (т. е. суммировать первые элементы всех массивов, вторые элементы и т.д.). Если это не так, то запрос потребует дополнительной логики для корректной об
Колоночные СУБД как раз для таких целей и есть. 
Попробуй хранить в MariaDB ColumnStore в 200 колонок.
Смотрим здесь . Получаем для обычного INT 4 байта на одно число, для BIGINT 8 байт. 
200 * 4 * 10'000'000 = 8'000'000'000 или 8Gb.
200 * 8 * 10'000'000 = 16'000'000'000 или 16Gb.
По нынешним меркам сущие пустяки.
Хранить, конечно же, нужно в нормальной форме, иначе суммирование придётся делать в приложении.
Похожие вопросы