Какую key-value БД использовать с данными в 10 млрд строк записей?

Какую "key-value" БД использовать для хранения 10 или более млрд строк данных?

Критерии:
- довольно быстрый импорт
- быстрый поиск/получение значения по ключу
- возможность одному значению задавать 5 ключей и более (некоторые ключи могут совпадать)

Как выглядят мои данные:
key_1 = 5 символов | key_1 = 6 символов | key_3 = 7 символов и более = значению в 120 символов (какие символы используются: 0-9 A-Z a-z)

Что я использовал раньше:
Раньше нужно было использовать один ключ/значение и данных было в районе ~ 800 млн записей и я использовал Redis (512 RAM) без снапшотов, в случае падения я заново нагружал, довольно таки быстрым импортом.

С чем я столкнулся в MySQL:
На данный момент данные построчно записанны в .txt которые я переконвертировал в .sql и попробовал использовать MySQL, для теста решил загрузить 200 млн строк, для всех столбцов использовал тип VARCHAR задав каждом столбцу нужную мне длину, импорт прозошел очень быстро, по поиск/получение занимал до 2 минут и я погуглив понял что нужно добавить на ключи индексацию, сделав это - поиск занимал до миллисекунды. НО с какими проблемами я столкнулся дальше: если создать пустую структуру и задать столбцам сразу индекс быстрый импорт превращается в очень медленный, будто скорость -x100, и я подумал без индексов загрузить сразу 5 млрд записей а дальше задать индексы но не тут та было спустя ~ 6 часов обработки ошибка "ERROR 1034 (HY000): Index for table 'TABLE_NAME' is corrupt; try to repair it"
  • Вопрос задан
  • 1395 просмотров
Пригласить эксперта
Ответы на вопрос 4
mayton2019
@mayton2019
Bigdata Engineer
Несколько мыслей.

1) У меня устойчивое дежа-вю. Периодически в топик заходят люди с именно этим вопросом. Разница только в количестве. Кому 1 млрд. Кому 10. Можно также поискать и слинковать эти вопросы в один большой вопрос.

2) MySQL который указан в тегах - нормально справляется с этой задачей. Он и не такое число строк
умеет хранить. И если взять MariaDb - там есть куча новых engines которые можно крутить для тюнинга
именно скорости чтения. Разумеется жертвуя чем-то другим. Транзакциями и записью например.

3) Непонятно что такое минимальное время? Если использовать дисковую БД типа MySQL то деградация времени
поиска будет примерно зависеть от логарифма количества строк. Тоесть деградация будет но очень медленно.
Для 10 млрд индекс по key будет содержать порядка 4-5 уровней BTree дерева. Тоесть дисковой системе
нужно будет сделать до 5 или до 6 рандомных чтений (если нужные данные лежат в таблице). Это достаточно
быстро для того чтобы моргнуть глазом за это время. Рандомное чтение любого блока из магнитного диска
класса SATA-3 занимает порядка 20 милисекунд. Тоесть для 5 уровней - это 100 милисекунд. Для дисков
класса SSD и это время можно уже считать меньше милисекунды. Точно я не знаю надо мерять.

Испортить это время может сетевой лаг который в данной задаче мы просто не учитываем. Считаем что сеть идеальна.

4) Непонятно зачем здесь указан Redis. Его задача не хранить 10 млрд а хранить только горячие
ключи по котороым идет очень частый доступ. Если автор хочет In-memory хранение - то время можно
еще сильнее улучшить. Его можно свести практически до нуля (я вангую несколько микро-секунд)
но придется прикупить планок памяти побольше и посчитать сколько памяти
надо для 10 млрд key/values неизвестной длины. Вообще крутить регулятор в направлении
микро-секунд нет особого смысла т.к. другие звенья вашего стека (приложение и сеть) могут
быть на порядки медленнее а это вообще нивелирует всю пользу от такой оптимизации.
Ответ написан
@rPman
Ответ зависит от требований к данным и особенностей записи, многопользовательская или нет (транзакции на запись - сильно выставляет требования к ресурсам), есть ли модификация данных (очень важный момент роняющий производительность в зависимости, правда если данные фиксированного размера то возможно не сильно), виды запросов на поиск и аналитику, (кому то нужны поиск по значению, а кому то сравнения больше/меньше, поиск min/max и сортировки, кому то нужны группировки по значению в индексе и многое другое), наличие упорядоченных данных (когда данные записываются последовательно и в запросах часто фигурирует выгрузка данных на интервале).

Отличный пример - числовое ключевое поле с монотонным ростом без пропусков позволяет использовать самый простой индексный файл где значение ключевого поля это смещение слова (например 4 байта) в индексном файле, а эти слова - это смещение в файле данных (например номер кластера фс, данные выровнены по нему). Файл данных это тупая последовательность размер+данные без разделителя.

Достоинства - максимальная из возможных производительность (файл данных и индексный файл могут храниться без файловой системы прямо в блочных устройствах), буквально 2 запроса на запись/поиск (при использовании файловых систем операций будет в несколько раз больше), ни одна универсальная база данных не даст такой. Кода - строк 20-30 на любом языке программирования, красиво можно пользоваться memory mapped files (они дают самую быструю работу с файлами и удобную под задачу). Данные пишутся линейно на диск (оптимально для hdd, само собой если не одновременно с чтением), большинство файловых и операционных систем поддерживают sparce файлы (будут накладные расходы, но константа), это значит можно с некоторыми оговорками пользоваться большими пропусками в порядке индексов (дырка в файле вернет нули, на диске храниться не будет).

Недостатки/особенности - требуется некий роутер, для управления несколькими файлами, если размер данных может выходить за пределы имеющихся устройств (в реляционных базах данных для этого есть прозрачный механизм tablespace), но на практике красивых монотонных индексов не существует и приходится выкручиваться, например группировать данные

Пример - временной ряд, в секунду происходят тысячи событий, хранить группами по секунде, т.е. ключевое поле для индекса - это timestamp-стартовое время файла, при среднем размере информации о событии в 100байт и 4 тысячи событий в секунду, на 3терабайтовый диск hdd индексы будут порядка 30 мегабайт, что прекрасно влезает в оперативную память. У меня самый дешевый toshiba3тб выдавал 60 req/sec случайных запросов (как в синтетических бенчмарках), при этом запрашивать можно было сразу большими интервалами, что роняло скорость максимум в 2-3 раза, пока данные влезали на дорожку (в зависимости от расположения там по разному). Последовательное чтение данных само собой работало на максимуме скорости диска в 150-200мб/с.
p.s. от такой модели отказался за ненадобностью, данные хорошо упаковывались большими блоками (в 10 раз), храню теперь просто в архивах большими блоками по несколько часов, на время работы нужные данные переливаются во временные файлы.

Помню тут на хабре была статья где человек залил в mssql миллионы записей, и радовался секундам на запрос (правда там хеши но это не так важно, для них тоже есть решения)
Ответ написан
uvelichitel
@uvelichitel
habrahabr.ru/users/uvelichitel
bitcoin blockchain клиенты, (классический на С и популярный на Go) употребляют lmdb www.lmdb.tech/doc
Ответ написан
Комментировать
@MakarExp
Я бы посмотрел в сторону кликхауса для таких данных, если можете обеспечить вставку пачками, вставка не частая и чтение не идёт по одной записи https://clickhouse.com/docs/ru
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы