Я думаю, вам следует рассмотреть возможность отделения поиска соответствующего ключа от доступа к базовой записи.
То, что вы, например, имеете структуру btree +, состоящую из простых ключей, в которой вы находите первую совпадающую запись, затем вы следуете перечислителю btree +, пока не найдете соответствие.
Аналогично некластерному индексу в базе данных. Сначала вы найдете ключ, затем вы найдете запись.
Ваши примеры "Jo" и "John" в "Johnson" являются примерами "StartsWith ()", где сортировка ключей принесет вам пользу. Если вы также ожидаете искать простую подстроку, а не только начальный сегмент, вам нужно взглянуть на другие алгоритмы хранения и поиска ключа.
Если вы не уверены, что вам обоим это нужно, и вы сможете использовать оптимизированный поиск, вам нужно просто выполнить сканирование в памяти по всем ключам, а затем сосредоточиться на оптимизации соответствующего предиката.
Например, с помощью опции Regex предварительной компиляции поиска.