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