С Boost.MultiIndex вам не нужно целых 12 индексов (кстати, число перестановок в 4 элементах равно 4! = 24, а не 12), чтобы охватить все запросы, содержащие определенное подмножество из 4 ключей: спасибо для использования составных ключей и с небольшой изобретательностью достаточно 6 индексов.
По счастливой случайности я несколько лет назад привел в своем блоге пример, показывающий, как это сделать почти точно так же, как в вашем конкретном сценарии:
Многоатрибутный запрос с Boost.MultiIndex
Предоставляется исходный код, который вы можете использовать с небольшими изменениями в соответствии с вашими потребностями. Теоретическое обоснование конструкции также приведено в серии статей того же блога:
Математика, стоящая за этим, не тривиальна, и вы можете спокойно ее игнорировать: если вам нужна помощь в ее понимании, не стесняйтесь комментировать статьи блога.
Сколько памяти использует этот контейнер? В типичном 32-разрядном компьютере размер ваших объектов составляет 4 * sizeof (int) + sizeof (double) + sizeof (short) + padding, что обычно дает 32 байта (проверено в Visual Studio на Win32). К этому Boost.MultiIndex добавляются накладные расходы в 3 слова (12 байт) на каждый индекс, поэтому для каждого элемента контейнера вы получаете
32 + 6 * 12 = 104 байта + заполнение.
Опять же, я проверил в Visual Studio на Win32, и полученный размер составлял 128 байт на элемент. Если у вас есть 1 миллиард (10 ^ 9) элементов, то 32 бита недостаточно: переход на 64-битную ОС, скорее всего, удвоит размер объектов, поэтому необходимая память будет составлять 256 ГБ, что является довольно мощным зверь (не знаю, используете ли вы что-то такое огромное)