Какой можно применить алгоритм для хранение индекса для 50 миллиардов записей в golang?

В результате работы программы получается около 50 миллиардов записей вида
<id string(60)> <source string(32)> <subid uint64>
и каждый день добавляются новые записи.

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

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

Может кто-то сможет подсказать название алгоритма или библиотеку на go или проект на go в котором реализованно что-то похожее. Требуется
1) Хранить индекс в нескольких файлах. Например у нас есть большой индекс и нужно добавить еще немного записей, перестройка индекса скорее всего трудный процесс, поэтому просто кладем рядом кусочек индекса и используем его тоже
2) Объединять индексы, те когда файлов уже много, можно пересобрать индекс
3) Удалять дубликаты/обновлять индекс . если приходит запись с уже существующим id + source то использовать последние данные.

У нас 50 миллиардов записей и они прибывают, по 200-300к каждый день.
  • Вопрос задан
  • 584 просмотра
Пригласить эксперта
Ответы на вопрос 5
mayton2019
@mayton2019
Bigdata Engineer
Немного бухгалтерии. Если взять по максимуму.

Размер одной записи должен быть порядка 60 + 32 +8 = 100 символов (байт для простоты)

При 50 млрд записей объем хранимых данных должен быть порядка

50 000 000 000 * 100 = 5 000 000 000 000 = 5 триллионов байт.

В дисковом хранении это будет примерно 4.5 терабайта. Задачка для in-memory неподъемная. Нужен диск + мемори.

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

Вобщем нужна дисковая БД которая встраивается в приложение. На требование менеджеров которые запретили использовать БД забейте. Они ничего не понимают. Делайте БД встраиваемую в приложение. В качестве таких (встраиваемых систем можно поробовать) LevelDb, BerkeleyDb, RocksDb. Они поддерживают индекс класса B+Tree и это даст возможность искать группы записей по одному ID. Для этого класса систем любую запись можно найти за 4-5 дисковых IOPS. Если какдый IOPS стоит 15 мс (это я так мерял свой собственный магнитный HDD) то любой поиск группы ключей для TTFB будет порядка 15 * 5 = 75 милисекунд. Ну если вы поставите SSD - то быстрее.

По поводу предложений хранить в файлах. До того как обсуждать это - надо уяснить требования по времени отклика. Сколько секунд вы согласны ждать - насколько можно и партицировать (или шардировать ваш файл).
В простейшем случае мы делим большой CSV файл на 512 partitions по хешу от ID и получаем соотв время фулл-скана всего файла поделенное на 512. Дальше - играйтесь с этим параметром партишенинга выводя его на доступный уровень отклика. Из недостатков - будет россыпь файлов. Надо почиать документацию на вашу файловую систему (ext4?) и тюнить ее так чтоб она не сдохла от такого числа inodes.

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

По поводу Parquet. Не взлетит. Скорее всего индекс по данному типу файла - это совсем не то что вкладывают туда релационные системы. Обычно Parquet/Orc/Delta вкладывают в индекс смысл - отбрасывания тех полосок данных (stripes) которые бесполезны при чтении всего файла. Такой индес - обычно просто либо range-признак либо карта Блума. И в случае с range - дает эффект на сортированных данных. Для прочих - будет бесполезно т.к. фулл-скан все равно обеспечен. А если фулл-скан то зачем тогда вообще индекс.

Вобщем для дизайна архитектуры нам нужны цифры. Средние длины по колонкам. И я-бы еще запросил кардинальность по полю ID.
Ответ написан
Apache Parquet вполне может подойти, т.к. это формат хранения, а не движок. Есть реализации на Го. Хранить можно на любом подходящем хранилище. Индексы колонок тоже поддерживаются.
Ответ написан
Комментировать
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
vgray, Удаляются ли записи?

Так-то, поиск на полное совпадение по строке не самое сложное. Какое-нибудь B-Tree или Trie - отлично подойдут тут. Проблема только в том, что оно в память не влезает, поэтому придется повозиться с хранением этого всего кусками в файлах. B-Tree как раз для этого и сделано, но оно будет медленнее работать со строками. Аккуратно порезанный на куски Trie будет быстрее.
Ответ написан
Комментировать
dollar
@dollar
Делай добро и бросай его в воду.
Можно индексировать индекс. А именно, хранить, например, в 10 файлах: в первом все id % 10 == 1, во втором id % 10 == 2 и т.д. Если id - строки, то по первой букве, например. По сути это хеширование. Если потом перестраивать, то не всё и сразу, а тоже по 10% от всего индекса за раз. Это как пример.
Ответ написан
dimonchik2013
@dimonchik2013
non progredi est regredi
reindexer

он завязан на inmemory, но на Го, возможно, алгоритмы подойдут
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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