Cassandra: запрос с предложением where, содержащим greather - или меньше

Я использую Cassandra 1.1.2 я пытаюсь преобразовать приложение RDBMS в Cassandra. В моем приложении RDBMS у меня есть следующая таблица под названием table1:

| Col1 | Col2 | Col3 | Col4 |
  1. Col1: строка (первичный ключ)
  2. Col2: строка (первичный ключ)
  3. Col3: Bigint (index)
  4. Col4: Bigint

эта таблица насчитывает более 200 миллионов записей. В основном используется запрос что-то типа:

Select * from table where col3 < 100 and col3 > 50;

в Кассандре я использовал следующее инструкция для создания таблицы:

create table table1 (primary_key varchar, col1 varchar, 
col2 varchar, col3 bigint, col4 bigint, primary key (primary_key));

create index on table1(col3);

Я изменил первичный ключ на дополнительный столбец (я вычисляю ключ внутри моего приложения). После импорта нескольких записей я попытался выполнить следующий cql:

select * from table1 where col3 < 100 and col3 > 50;

такой результат:

Bad Request: No indexed columns present in by-columns clause with Equal operator

Запрос выбрать столбцы col1,столбец col2,с col3,col4 из table1 где кол3 = 67 работает

Google сказал, что нет способа выполнить такого рода запросы. Это правда? Любой совет, как создать такой запрос?

2 ответов


индексы Cassandra фактически не поддерживают последовательный доступ; см. http://www.datastax.com/docs/1.1/ddl/indexes для хорошего быстрого объяснения того, где они полезны. Но не отчаивайтесь; более классический способ использования Cassandra (и многих других систем NoSQL) - денормализовать, денормализовать, денормализовать.

это мая будет хорошей идеей в вашем случае использовать классический шаблон диапазона ведра, который позволяет использовать рекомендуемый RandomPartitioner и держите ваши строки хорошо распределенными вокруг вашего кластера, все еще позволяя последовательный доступ к вашим значениям. Идея в данном случае заключается в том, что вы хотели сделать вторую динамическое отображение columnfamily (по периодам и заказал) col3 значения в соответствующие primary_key значения. В качестве примера, если ваш col3 значения варьируются от 0 до 10^9 и довольно равномерно распределены, вы можете поместить их в 1000 ведер диапазона 10^6 каждый (лучший уровень детализации будет зависеть от типа запросов, которые вы потребность, вид данных, которые у вас есть, время запроса туда и обратно и т. д.). Пример схемы для cql3:

CREATE TABLE indexotron (
    rangestart int,
    col3val int,
    table1key varchar,
    PRIMARY KEY (rangestart, col3val, table1key)
);

при вставке в table1, вы должны вставить соответствующую строку в indexotron С rangestart = int(col3val / 1000000). Затем, когда вам нужно перечислить все строки в table1 С col3 > X, вам нужно запросить до 1000 ведер indexotron, а все col3vals внутри будет отсортирован. Пример запроса, чтобы найти все table1.primary_key ценности, за которые table1.col3 < 4021:

SELECT * FROM indexotron WHERE rangestart = 0 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 1000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 2000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 3000 ORDER BY col3val;
SELECT * FROM indexotron WHERE rangestart = 4000 AND col3val < 4021 ORDER BY col3val;

если col3 всегда известны небольшие значения / диапазоны, вы можете уйти с более простой таблицей, которая также сопоставляется с исходной таблицей, например:

 create table table2 (col3val int, table1key varchar,
                      primary key (col3val, table1key));

и использовать

 insert into table2 (col3val, table1key) values (55, 'foreign_key');
 insert into table2 (col3val, table1key) values (55, 'foreign_key3');
 select * from table2 where col3val = 51;
 select * from table2 where col3val = 52;
 ...

или

 select * from table2 where col3val  in (51, 52, ...);

может быть хорошо, если у вас нет слишком больших диапазонов. (вы также можете получить тот же эффект со своим вторичным индексом, но вторичные индексы не рекомендуется?). Может теоретически распараллелить это "локально на стороне клиента", как что ж.

кажется, что "Кассандра" должна иметь какой-то ключ, например "userid", и вы используете его в качестве первой части "всех ваших запросов", поэтому вам может потребоваться переосмыслить вашу модель данных, тогда у вас могут быть такие запросы, как select * from table1 where userid='X' and col3val > 3 и он может работа (предполагая ключ кластеризации на col3val).