Cassandra - Как получить самое последнее значение

У меня есть следующая таблица, определенная в Cassandra 2.0.9:

CREATE TABLE history
(
    histid      uuid,
    ddate           text,       -- Day Date, i.e. 2014-11-20
    valtime         timestamp,  -- value time
    val             text,       --value
    PRIMARY KEY ((histid , ddate), valtime )
)
WITH CLUSTERING ORDER BY (valtime desc)
;

Скрипты ежедневно вставляют в эту таблицу несколько тысяч строк.

Мне нужно иметь возможность выбирать из этой таблицы, зная только гистид. Однако я разделил строки, используя (histid, ddate). Это означает, что у меня есть полный день значений истории для каждой строки.

Чтобы выбрать из этой таблицы определенный гистид, мне также нужно предоставить столбец ddate. Например:

SELECT * FROM history
WHERE histid= cebc4c80-daa6-11e3-bcc2-005056a975a4
AND ddate = '2014-05-16'
;

Чтобы получить самое последнее значение, я могу сделать следующее:

SELECT * FROM history
WHERE histid= cebc4c80-daa6-11e3-bcc2-005056a975a4
AND ddate = '2014-05-16'
LIMIT 1
;

Однако, если мне нужно самое последнее значение для любого данного histid, я не могу отправить запрос, не зная, что такое ddate, поскольку он является частью ключа раздела.

Итак... я спрашиваю, как лучше всего подойти к этому?

Это то, что я сделал, но я не знаю, разумно ли это:

Я создал дополнительную таблицу:

 CREATE TABLE history_date
(
    histid          uuid,
    maxdate         timestamp, -- most recent date
    PRIMARY KEY (histid)
);

Когда строка вставляется в таблицу истории, строка также вставляется в эту таблицу с помощью (histid, valtime).

Тогда наш программный код может:

1.  query the history_date table for a particular id
2. take the "maxdate" column (truncate it to yyyy-mm-dd)
3. use the histid and truncated maxdate to query the history table to retrieve the most recent value.

Так что это работает. Но на самом деле это не похоже на хорошее решение.

Есть ли лучший способ сделать это, возможно, только с одной таблицей?

Спасибо за ваше время.


person iamtheoracle    schedule 27.01.2015    source источник
comment
Моделирование данных для Cassandra — это другое мышление, и подход с избыточными данными/таблицей запросов является правильным.   -  person Aaron    schedule 27.01.2015
comment
@BryceAtNetwork23 - Спасибо. Да, конечно, иногда трудно уложить в голове. Цените обратную связь.   -  person iamtheoracle    schedule 27.01.2015
comment
@iamtheoracle Это сложно. Суть в том, чтобы признать, что необходим другой образ мышления, и вы преодолели это препятствие, так что вы на правильном пути. Дальше, чем многие, кто, кажется, так и не понял. :) Придерживайтесь этого, и со временем это будет иметь больше смысла.   -  person Don Branson    schedule 27.01.2015
comment
@DonBranson Спасибо, что более 20 лет использования других основных баз данных погубили меня :)   -  person iamtheoracle    schedule 28.01.2015
comment
@iamtheoracle Хех. Что ж, я достаточно долго программировал, чтобы помнить последний сдвиг парадигмы к базам данных SQL.   -  person Don Branson    schedule 28.01.2015


Ответы (3)


Одна вещь, которую вы можете попробовать, это создать новую таблицу, разделенную на более широкий диапазон дат, например month. Таким образом, вам просто нужно знать месяц для запроса.

CREATE TABLE history_by_month(
    histid          uuid,
    ddate           text,       -- Day Date, i.e. 2014-11-20
    valtime         timestamp,  -- value time
    val             text,       --value
    month           text,
    PRIMARY KEY (month, valtime, histid))
WITH CLUSTERING ORDER BY (valtime desc, histid asc);

Теперь этот запрос должен вернуть то, что вы ищете:

SELECT * FROM history_by_month
WHERE month = '2014-05'
LIMIT 1;

Единственное, что нужно иметь в виду, это то, что если вы получите слишком много записей за один месяц, вы столкнетесь с вероятностью того, что ваши разделы будут слишком большими. Если это станет проблемой, вы можете подумать о сужении этого фокуса до недели.

Кроме того, всем, кто все еще использует 2.0.9, следует подумать об обновлении. Даже самый последний уровень исправления 2.1 намного более стабилен.

person Aaron    schedule 25.06.2019
comment
Наличие большего раздела не решает проблему. Это все тот же вопрос: как мне определить месяц для использования в запросе. Мне просто интересно, есть ли общее решение, кроме того, которое придумал ОП? - person Ihor Kaharlichenko; 25.06.2019
comment
@IhorKaharlichenko, к сожалению, у Кассандры очень строгие требования к запросам, и для того, чтобы немного сузить их, потребуется некоторое знание временных рамок. - person Aaron; 25.06.2019

Ну, как вы упомянули, вы не можете выбрать, зная только одно значение таблицы, разделенной двумя ключами. Тем не менее, кластеризация порядка и порядка по пределу может помочь, которые вы уже использовали.

http://www.datastax.com/documentation/cql/3.1/cql/cql_reference/refClstrOrdr.html

https://cassandra.apache.org/doc/cql3/CQL.html#selectStmt

person safato    schedule 27.01.2015

Я думаю, что решение прямое, нет необходимости усложнять вещи. просто сделайте ключ раздела в 'histid' и ключ кластеризации в 'ddate'. Итак, ваш DDL должен выглядеть так, как показано ниже.

CREATE TABLE history ( histid uuid, ddate text, valtime timestamp, val text, PRIMARY KEY ((histid), ddate, valtime));

Вы можете запросить из любой приведенной ниже комбинации (но убедитесь, что тот же порядок в вашем предложении where) а) запрос только по histid b) запрос по histid и dddate c) запрос по histid , dddate и valtime

Дайте мне знать, если это работает для вас, или у вас все еще есть вопросы?

person Chandan Goel    schedule 23.02.2021