Подтвердить что ты не робот

Эффективное хранение 7.300.000.000 строк

Как вы могли бы решить следующую проблему хранения и поиска?

Примерно 2.000.000 строк будут добавляться каждый день (365 дней/год) со следующей информацией в строке:

  • id (уникальный идентификатор строки)
  • entity_id (принимает значения от 1 до 2.000.000 включительно)
  • date_id (увеличивается с каждым днем) будет принимать значения от 1 до 3,650 (десять лет: 1 * 365 * 10))
  • value_1 (принимает значения от 1 до 1.000.000 включительно)
  • значение_2 (принимает значения от 1 до 1.000.000 включительно)

entity_id в сочетании с date_id уникален. Следовательно, в таблицу может быть добавлено не более одной строки на сущность и дату. База данных должна иметь возможность хранить 10-дневную ежедневную информацию (7,300,000,000 строк (3,650 * 2,000,000)).

То, что описано выше, - это шаблоны записи. Шаблон чтения прост: все запросы будут выполняться на определенном объекте_ид. То есть получить все строки, описывающие entity_id = 12345.

Поддержка транзакций не требуется, но решение для хранения должно быть открыто. В идеале я бы хотел использовать MySQL, но я открыт для предложений.

Теперь - как бы вы справились с описанной проблемой?

Обновление: Мне было предложено подробно рассказать о шаблонах чтения и записи. Записи в таблице будут выполняться в одной партии в день, когда новые записи 2M будут добавлены за один раз. Считывание будет производиться непрерывно с каждым чтением каждую секунду.

4b9b3361

Ответ 1

Используйте partitioning. С вашим шаблоном чтения вы захотите разделить на entity_id hash.

Ответ 2

"Теперь - как бы вы справились с описанной проблемой?"

С простыми плоскими файлами.

Вот почему

"все запросы будут выполняться на конкретный объект_ид. То есть извлекать все строки, описывающие entity_id = 12345."

У вас есть 2.000.000 объектов. Разделение на основе номера объекта:

level1= entity/10000
level2= (entity/100)%100
level3= entity%100

Каждый файл данных level1/level2/level3/batch_of_data

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

Если кто-то хочет реляционную базу данных, загрузите файлы для данного объекта entity_id в базу данных для их использования.


Изменить В числовых номерах.

  • Правило уникальности date_id/entity_id не является чем-то, что нужно обрабатывать. Он (а) тривиально наложен на имена файлов и (б) не имеет отношения к запросу.

  • date_id "опрокидывание" ничего не значит - нет запроса, поэтому нет необходимости переименовывать что-либо. date_id должен просто расти без привязки к дате эпохи. Если вы хотите очистить старые данные, удалите старые файлы.

Поскольку никакой запрос не зависит от date_id, с ним ничего не должно быть сделано. Это может быть имя файла для всего, что имеет значение.

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


Изменить при открытии/закрытии

Для записи вам необходимо оставить файл открытым. Вы делаете периодические флеши (или закрываете/открываете), чтобы убедиться, что на самом деле что-то происходит на диске.

У вас есть два варианта архитектуры вашего автора.

  • У вас есть один "писательский" процесс, который объединяет данные из разных источников. Это полезно, если запросы относительно часты. Вы платите за объединение данных во время записи.

  • Несколько файлов открываются одновременно для записи. При запросе объедините эти файлы в один результат. Это полезно, потому что запросы относительно редки. Вы платите за объединение данных во время запроса.

Ответ 3

Вы можете посмотреть на эти вопросы:

Большой первичный ключ: 1 + миллиард строк MySQL + InnoDB?

Большие таблицы MySQL

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

НТН.

S

Ответ 4

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

Представьте, что ваши данные выложены на диске в виде массива записей фиксированной длины 2M (по одному на каждый объект), каждый из которых содержит 3650 строк (по одному в день) 20 байтов (строка для одного объекта в день).

Ваш шаблон чтения читает одно сущность. Он смежен на диске, поэтому требуется 1 поиск (около 8 мс) и чтение 3650x20 = около 80K, возможно, 100 Мбайт/с... так что это делается за долю секунды, что легко соответствует вашему 1-запросу в секунду чтению шаблон.

Обновление должно записать 20 байтов в 2M разных местах на диске. В простейшем случае это потребует 2M запросов, каждый из которых занимает около 8 миллисекунд, поэтому потребуется 2M * 8ms = 4,5 часа. Если вы будете распространять данные на 4-х дисках "raid0", это может занять 1,125 часов.

Однако места расположены всего на расстоянии 80 тысяч. В том случае, если в блоке размером 16 МБ имеется 200 таких мест (типичный размер кэша диска), он может работать на чем угодно до 200 раз быстрее. (1 минута) Реальность находится где-то между ними.

Мой механизм хранения работает с такой философией, хотя это немного более общая цель, чем массив с фиксированной длиной.

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

Кстати, вы можете исключить идентификатор даты и объекта из сохраненной строки (потому что это индексы массива) и может быть уникальным идентификатором - если вам это действительно не нужно, поскольку (идентификатор объекта, дата) уникально, и сохраните 2 значения как 3-байтовый int. Затем ваша сохраненная строка составляет 6 байт, и у вас есть 700 обновлений на 16 М и, следовательно, более быстрые вставки и меньший файл.

Изменить Сравнение с плоскими файлами

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

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

Поэтому, если вы используете плоские файлы, почему бы не использовать только один плоский файл и проиндексировать его?

Изменить по производительности

В производительности этого приложения будет преобладать время поиска диска. Вычисления, которые я сделал выше, определяют лучшее, что вы можете сделать (хотя вы можете сделать INSERT быстрее, замедляя SELECT - вы не можете сделать их лучше). Неважно, используете ли вы базу данных, плоские файлы или один плоский файл, кроме, которые вы можете добавить больше запросов, которые вам действительно не нужны, и замедлить их дальше. Например, индексирование (будь то индекс файловой системы или индекс базы данных) вызывает дополнительные операции ввода-вывода по сравнению с "поиском массива", и это замедлит работу.

Изменить на эталонных измерениях

У меня есть таблица, которая очень похожа на вашу (или почти точно как на один из ваших разделов). Это было 64 тыс. Единиц не 2М (1/32 твоего) и 2788 дней. Таблица была создана в том же порядке INSERT, что и ваш, и имеет тот же индекс (entity_id, day). SELECT на одном объекте занимает 20,3 секунды, чтобы проверить 2788 дней, что составляет около 130 запросов в секунду, как и ожидалось (на среднем диске времени поиска 8 миллисекунд). Время SELECT будет пропорционально количеству дней и не будет сильно зависеть от количества объектов. (Это будет быстрее на дисках с более быстрым временем поиска. Я использую пару SATA2 в RAID0, но это не имеет большого значения).

Если вы переупорядочиваете таблицу в порядке сущности   ALTER TABLE x ORDER BY (ENTITY, DAY) Тогда тот же самый SELECT занимает 198 миллисекунд (потому что он считывает сущность заказа в одном доступе на диск). Однако для выполнения операции ALTER TABLE выполнено 13.98 дней (для строк 182M).

Есть еще несколько вещей, которые показывают вам измерения 1. Ваш индексный файл будет размером с ваш файл данных. Это 3 ГБ для этой таблицы образцов. Это означает, что (в моей системе) весь индекс на диске ускоряет скорость памяти.

2. Ваша ставка INSERT будет логарифмически уменьшаться. INSERT в файл данных является линейным, но вставка ключа в индекс - это журнал. На 180 М записей я получал 153 INSERT в секунду, что также очень близко к скорости поиска. Он показывает, что MySQL обновляет блок индекса листа почти для каждого INSERT (как и следовало ожидать, поскольку он индексируется по объекту, но вставляется в дневной порядок.). Таким образом, вы смотрите на 2M/153 secs = 3.6hrs, чтобы ежедневно вставлять строки в 2M. (Разделенный на любой эффект, который вы можете получить по разделам между системами или дисками).

Ответ 5

У меня была аналогичная проблема (хотя и в гораздо большем масштабе - о вашем ежегодном использовании каждый день)

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

Не забудьте индексировать таблицу, иначе вы будете возиться с крошечной струйкой данных в каждом запросе; oh, и если вы хотите делать массовые запросы, использовать плоские файлы

Ответ 6

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

Это позволит вам рассмотреть возможность сжатия в некоторых столбцах.

Также рассмотрите архивирование и разбиение.

Ответ 7

Если вы хотите обрабатывать огромные данные с миллионами строк, его можно считать похожим на базу данных временных рядов, которая регистрирует время и сохраняет данные в базе данных. Некоторые из способов хранения данных - использование InfluxDB и MongoDB.