У меня есть довольно хитрый, терпите меня, поскольку я стараюсь не спотыкаться о свои слова здесь. Я провожу некоторые исследования, и моя группа переходит на базу данных cassandra. В нашем исследовании раньше использовался MySQL, но данные переросли базу данных (192 миллиона строк в памяти при 16G — это был единственный способ достаточно быстро запрашивать данные). Сами данные в некотором роде статичны. Их очень много, но на данный момент любые новые данные представляют собой несколько медленную струйку.
Данные состоят из множества пар классификатор-оценка. Мы формулируем запросы к базе данных, которые в основном говорят: «дайте мне 500 лучших для следующих классификаторов». Затем база данных возвращает это количество баллов. Например, если мы запрашиваем 500 лучших оценок для 2 классификаторов, мы получаем 1000 строк (каждая строка состоит из идентификатора классификатора и оценки, т. е. [4, 9100]). Сами оценки неравномерны (распределение имеет тенденцию сгущаться к одному концу значений, которые, кстати, находятся в диапазоне от -10000 до 10000).
При переходе на cassandra возникает ряд требований. Прежде всего, нам нужно иметь возможность запрашивать верхние и нижние оценки N для каждого классификатора. Обычно я вижу, что для этого подходит упорядоченный разделитель, однако, как я уже сказал, оценки имеют тенденцию накапливаться в крайних точках (что возлагало бы слишком большую нагрузку на один узел). Итак, мой первый вопрос: как мне равномерно распределить пары классификатор/оценка, сохраняя при этом возможность запрашивать верхние или нижние N.
Существует вторичное требование, которое в значительной степени портит первое. Иногда необходимо найти все оценки, которые близки к другой оценке. Поэтому, если я увижу классификатор 6 с оценкой 400, я могу попросить, покажите мне 500 оценок, которые наиболее близки к этому (все в пределах классификатора 6). Я абсолютно озадачен этим. Я читал, что cassandra поддерживает вторичные индексы (yay), но только хеш-тип (boo - без диапазонов). Создадим ли мы отдельное семейство столбцов для этого варианта использования?
И, наконец, скорость имеет первостепенное значение. Данные используются в интерактивном приложении с графическим интерфейсом. В идеале запросы должны занимать всего несколько секунд. И если все данные застревают на одном конкретном узле, это замедляет работу.
Мы испробовали все виды хитрых трюков. Наша лучшая идея заключалась в том, чтобы поместить данные в сегменты, чтобы первые 500 попали в сегмент 1, следующие 500 — в сегмент 2 и так далее. Преимущество в том, что для получения первых 500 мы просто запрашиваем корзину 1. Также все данные БУДЕТ равномерно распределены с использованием случайного разделителя. Однако, поскольку БОЛЬШИНСТВО наших запросов интересует только сегмент 1, это сильно нагрузит только один узел (помните, что если задействовано N классификаторов, на самом деле это 500 * N оценок на сегмент). Настоящим недостатком этой схемы является то, что она разваливается, когда нам нужно выполнить запрос на основе близости к счету (нам пришлось бы выполнить какой-то странный бинарный поиск по корзинам, чтобы найти наше начальное значение).
На данный момент у нас заканчиваются идеи. Все, что я видел о кассандре, заставляет задуматься, подходит ли оно вообще для этой задачи. Мы выбрали его в основном из-за его горизонтальной масштабируемости, что важно (намного проще добавить узел, чем сегментировать RDBM). Итак, я полагаю, что мой общий вопрос таков: как бы вы подошли к этому? Если Кассандра, пожалуйста, решите любую из вышеперечисленных проблем. В противном случае любое понимание или мудрость будут оценены. Спасибо.