ключ 49 бит - log(66^8) - пусть для простоты 8байт, значение 32 байта (у тебя там hex строка)
только на значения тебе нужно 30 терабайта на каждый триллион - 32*10^12 и даже в идеальном случае еще 16тб на индекс ключа (чем больше оптимизируешь хранение тем больше операций на чтение и запись каждой)
Недавно была
статья на хабре про тесты производительности работы mssql с похожими ключами миллионы записей
Я бы предложил схему с самописным индексом (мне кажется тут колхозить идеальнее всего).
* делишь ключ на 2 части (если бы ключ был не такой равномерный, то нужно было бы брать хеш от него), например по 4 байта
* младшие 4 байта (они наиболее равномерно будут распределены) - это номер блока в общем хранилище (на 1 триллион примерно 9кб, рекомендую. 16кб или 32кб, ssd на таких кластерах идеально работают), с массивом элементов: каждый из которых это вторые 4 байта ключа (старшие байты) + 32 байта искомое значение
для 16кб блока итоговое хранилище будет 70 тб - 2^32*16кб, можно прямо в дисковое устройство писать без файловой системы, по дискам пусть какой-нибудь рейд 0 раскидывает
* последняя запись в 16кб блоке - ссылка на дополнительное хранилище переполнений неравномерного распределения, его можно организовать как хочешь, на отдельном носителе
Итого
на каждый запрос ты делаешь ровно одно чтение 16кб блока с диска, в полученном массиве ищешь нужный ключ и получаешь значение (если нет значит переполнения из-за неравномерного заполнения индекса, топать в дополнительное хранилище), кстати можно читать по секторно в процессе поиска, тогда если диск сумеет это оптимизировать будет 2х профит. Запись то точно так же - 1 чтение 16кб и запись 1 сектора диска, дозапись в массив. Кстати, если контролировать порядоковый номер ключевого значения (а что то мне говорит там будет простой перебор всех паролей) то будет последовательная запись блоков на диск, для hdd это идеальная ситуация. Иначе всю оперативную память используешь как самодельный lazy write буфер, при переполнении записываешь его на диск, отсортировав согласно дисковым устройствам и отсортировав порядок номеров секторов (тогда либо понимать как работает рейд либо самому раскидывать по дискам), операционные системы и контроллер диска это умеют но у них кеш маленький.
Такой хеш самый быстрый из всех возможных, так как запилен под задачу, оверхед хранения десяток другой терабайт. Кодить тут минимум, строк сотня другая, и то половина - это код сетевого сервиса, ты ведь захочешь разнести сервис хранения и логику по сети.
Добавь еще один уровень, будет 2 чтения по 8-16кб (когда ты не на 2 части делишь ключевое значение а на 3, первая часть ссылается на список ссылок на вторую часть, которые уже ссылаются на блоки с третьей частью), можно уменьшить этот оверхед но мне кажется скорость в твоей задаче важнее, ведь она упадет в два раза.
Универсальные базы данных делают многоуровневые древовидные индексы (это настраивается) и ради удобства и универсальности ты теряешь в скорости.