Akdmeh
@Akdmeh
PHP, Yii2, Music

Как лучше хранить большой массив чисел на диске с очень быстрым поиском?

Представим, что есть массив типа:
{"1": [1,5,11,15,22,34...], "5": [55,44,22,67]}
То есть, много ключей (1, 5, 1005...) внутри одного ключа около 20 миллионов чисел, а в общем количество чисел может доходить до 800 миллионов.
Нужно постоянное хранение этой информации (то есть, вариант исключительно с оперативной памятью отпадает) и при этом организовать быстрый поиск вхождения определенного числа в эти огромные массивы (как я понимаю, должна помогать индексация). То есть, я должен иметь возможность быстро найти, входит ли чисто 505050 в массив с 20 миллионов чисел.
Какое решение посоветуете использовать?
Сейчас используется таблица MySQL, но она довольно медленная и уже показывает невысокую производительность. Redis работает быстрее, но когда число доходит до даже до 40 миллионов, начинает занимать 3.5 ГБ оперативки, а мы ведь даже не добрались до 100 миллионов...
Как я понимаю, наверняка существуют какие-то более быстрые и специфические базы данных, которые подходили бы мне для этой довольно узконаправленной задачи, но сеанс гугления на английском мне особо не помог.
Да, конечно же, это как-то нужно заставить работать с PHP (поэтому если есть какая-то библиотека для работы с подобным хранилищем - это будет огромным плюсом) :-D
Посоветуйте, в какую сторону мне искать решение? Буду благодарен за название хранилищ, которые помогут мне решить эту задачу. В приоритете, на самом деле - скорость поиска, так как если записей будет немного, то будет происходить много операций поиска. На задачу можно выделить около 10 ГБ оперативной памяти (но как я сказал, по моим подсчетам, Redis с этим не справляется).

Еще раз. Представим на примере Redis. Есть ключ big_array1, в нем хранится 20 миллионов цифр в формате SETS.
Самый частый запрос, который мы делаем:
sismember big_array1 1234567
То есть, узнаем, хранится ли в big_array1 число 1234567.
Вот эта функция для Redis работает отлично, но забирает слишком много оперативной памяти.
  • Вопрос задан
  • 225 просмотров
Пригласить эксперта
Ответы на вопрос 2
@deliro
Если допустимы ложноположительные ошибки (например, с шансом в 0,1%), то можно юзать фильтр Блума. Так ты 800млн значений впихнешь в 1,34гб. Чем меньше ошибка - тем больше нужно места
Ответ написан
Средствами реляционной БД и если не критична скорость вставки, то можно попробовать реорганизовать таблицу со строками
{"1": [1,5,11,15,22,34...], "5": [55,44,22,67]}
к виду {1:["1"], 5:["1"], ...., 22:["1", "5"]}, т.е. теперь первым стоит значение для проверки, потом массив ключей- поменять местами ключи со значениями.
Делаете 1 индекс.
Жрать ресурсов будем меньше+ скорость поиска, усложняется доступ к бывшим ключам вхождения("1", "2",...).
Можно попробовать создать 2 таблицы: первая просто число, которое нужно искать(скорость поиска О(1)+высота дерева в индексе), а вторую с ключами вхождения и внешний ключ к первой.
Ответ написан
Ваш ответ на вопрос

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

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