Cassandra получает все записи во временном диапазоне
Мне нужно работать с семейством столбцов, которое имеет (user_id, timestamp) в качестве ключа. В моем запросе я хотел бы получить все записи за определенный временной интервал, не зависящий от user_id. Это точная схема таблицы:
CREATE TABLE userlog (
user_id text,
ts timestamp,
action text,
app_type text,
channel_name text,
channel_session_id text,
pid text,
region_id text,
PRIMARY KEY (user_id, ts)
)
Я попытался запустить
SELECT * FROM userlog WHERE ts >= '2013-01-01 00:00:00+0200' AND ts <= '2013-08-13 23:59:00+0200' ALLOW FILTERING;
который отлично работает на моей локальной установке cassandra, содержащей небольшой набор данных, но с ошибкой
Request did not complete within rpc_timeout.
в продуктивной системе, содержащей все данные.
Есть ли запрос, предпочтительно cql, который выполняется гладко с данным семейством столбцов или мы должны изменить дизайн?
Ответы
Ответ 1
Тайм-аут - это то, что Cassandra занимает больше времени, чем таймаут (по умолчанию 10 секунд), чтобы вернуть данные. По вашему запросу Cassandra попытается извлечь весь набор данных перед возвратом. Для более чем нескольких записей это может занять больше времени, чем таймаут.
Для запросов, которые производят множество данных, вам нужно указать страницу, например.
SELECT * FROM userlog WHERE ts >= '2013-01-01 00:00:00+0200' AND ts <= '2013-08-13 23:59:00+0200' AND token(user_id) > previous_token LIMIT 100 ALLOW FILTERING;
где user_id
- предыдущий user_id. Вам также понадобится страница на ts, чтобы гарантировать, что вы получите все записи для последнего возвращаемого user_id.
В качестве альтернативы, в Cassandra 2.0.0 (только что выпущен) подкачка выполняется прозрачно, поэтому ваш исходный запрос должен работать без тайм-аута или ручного поискового вызова.
ALLOW FILTERING
означает, что Cassandra считывает все ваши данные, но только возвращает данные в указанном диапазоне. Это эффективно только в том случае, если диапазон - это большая часть данных. Если вы хотите найти записи, например, 5-минутное окно времени, это будет очень неэффективно.
Ответ 2
Кажется, что hotness для возможности запроса по времени (или любому диапазону) заключается в том, чтобы указать некоторый "другой столбец" как ваш раздел и затем укажите метку времени как "столбец кластеризации"
CREATE TABLE postsbyuser (
userid bigint,
posttime timestamp,
postid uuid,
postcontent text,
PRIMARY KEY ((userid), posttime)
) WITH CLUSTERING ORDER BY (posttime DESC);
вставить поддельные данные
insert into postsbyuser (userid, posttime) values (77, '2013-04-03 07:04:00');
и запрос (важная часть заключается в том, что это "быстрый" запрос и ALLOW FILTERING
не требуется, как это должно быть):
SELECT * FROM postsbyuser where userid=77 and posttime > '2013-04-03 07:03:00' and posttime < '2013-04-03 08:04:00';
Вы также можете использовать трюки для group by day (и, таким образом, иметь возможность запрашивать по дням), а что нет.
Если вы используете трюк стиля "group by day", тогда вторичным индексом также будет опция (хотя вторичные индексы, похоже, работают только с оператором "EQ" =
).