2015-07-10 74 views
5

我試圖顯示傳感器列表中的最新值。該列表還應該可以通過時間戳進行排序。通過Cassandra中的時間戳訂購最新記錄

我嘗試了兩種不同的方法。我包括傳感器的在主鍵的更新時間:

CREATE TABLE sensors (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, changedate) 
) WITH CLUSTERING ORDER BY (changedate DESC); 

然後我可以選擇列表是這樣的:

select * from sensors where customerid=0 order by changedate desc; 

這導致這樣的:

customerid | changedate    | sensorid | value 
------------+--------------------------+----------+------- 
      0 | 2015-07-10 12:46:53+0000 |  1 |  2 
      0 | 2015-07-10 12:46:52+0000 |  1 |  1 
      0 | 2015-07-10 12:46:52+0000 |  0 |  2 
      0 | 2015-07-10 12:46:26+0000 |  0 |  1 

問題是,我沒有得到最新的結果,但也得到了所有的舊值。

如果我從主鍵中刪除更改,則select一起失敗。

InvalidRequest: code=2200 [Invalid query] message="Order by is currently only supported on the clustered columns of the PRIMARY KEY, got changedate" 

更新的傳感器值也沒有選項:

update overview set changedate=unixTimestampOf(now()), value = '5' where customerid=0 and sensorid=0; 
InvalidRequest: code=2200 [Invalid query] message="PRIMARY KEY part changedate found in SET part" 

失敗的原因CHANGEDATE是主鍵的一部分。

是否有任何可能的方法來存儲每個傳感器的最新值,並且還通過時間戳記來保存表格?

編輯: 在此期間,我嘗試了另一種方法,只存儲最新值。

我用這個模式:

CREATE TABLE sensors (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, sensorid, changedate) 
) WITH CLUSTERING ORDER BY (changedate DESC); 

將最新的值之前,我會刪除所有舊值

DELETE FROM sensors WHERE customerid=? and sensorid=?; 

但這種失敗,因爲changedate沒有WHERE子句的一部分。

+0

這似乎是經典檢索每組問題中的最後一條記錄。即獲取每個sensorID的最新讀數。 – malhal

回答

2

問題是,我沒有得到最新的結果,而是所有的舊值。

既然你是在DESC的聚簇順序存儲,它總是會很容易得到最新的記錄,所有你需要做的是「限制」添加到您的查詢,即:

select * from sensors where customerid=0 order by changedate desc limit 10; 

最多可以返回10條記錄,其中包含最多的記錄。即使您使用限制,但您仍然保證獲得最新記錄,因爲您的數據是以這種方式訂購的。

如果我從主鍵中刪除changedate,select會一起失敗。

這是因爲你不能在不是集羣密鑰(主鍵的次要部分)的列上排序,除了可能有一個輔助索引,我不建議這樣做。

更新傳感器數值也沒辦法

你的更新查詢失敗,因爲它是不合法的,包括在「設置」中的主鍵的一部分。爲了使這項工作,所有你需要做的就是更新您的查詢,包括在where子句中CHANGEDATE,即:

update overview set value = '5' and sensorid = 0 where customerid=0 and changedate=unixTimestampOf(now()) 

有隻存儲從每個傳感器的最新值,並保留任何可能的方式表按時間戳排序?

您可以通過創建一個名爲'latest_sensor_data'的獨立表格,使用與主鍵例外相同的表格定義來執行此操作。主鍵現在是'customerid,sensorid',因此每個傳感器只能有一個記錄。創建單獨表格的過程稱爲denormalization,並且是Cassandra數據建模中的常見使用模式。當您插入傳感器數據時,您現在可以將數據插入'傳感器'和'latest_sensor_data'中。

CREATE TABLE latest_sensor_data (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, sensorid) 
); 

在卡桑德拉3.0 'materialized views'將出臺,這將使這個不必要的,因爲你可以使用物化視圖來完成這個要求。

現在做下面的查詢:

select * from latest_sensor_data where customerid=0 

會給你每個傳感器爲客戶的最新值。

我建議將'傳感器'重命名爲'sensor_data'或'sensor_history',以使其更清楚數據是什麼。此外,您應該將主鍵更改爲'customerid,changedate,sensorid',因爲這可以讓您在同一日期有多個傳感器(這似乎是可能的)。

+0

另一個說明,如果你想要更多的最新值(即最後10個值),它會變得更加困難。在C * 2.2中,您可以使用用戶定義的聚合來讓cassandra爲您的傳感器表獲取每個傳感器的10個「最新」值。你也可以看看使用spark-cassandra連接器來偶爾爲你計算。 –

+0

你的建議的問題是,我放棄了用'changedate'排序的能力。 – user5102859

+0

我提出了兩個表,其中一個在changedate('sensor_history'表)上有一個聚簇鍵,另一個聚集在sensorid上。 –

2

您的第一種方法看起來很合理。如果您向查詢添加「限制1」,則只會獲得最新結果,或限制2以查看最新的2個結果等。

如果要從表中自動刪除舊值,則可以指定插入時的數據點的TTL(生存時間)。因此,如果您想保留10天的數據點,您可以在插入語句中添加「USING TTL 864000」。或者你可以爲整個表設置默認的TTL。

+0

這裏我不能使用TTL,因爲沒有保證的時間跨度,傳感器報告值。它可能保持沉默幾天,幾周甚至幾個月。但我仍然需要保留最新的價值。 – user5102859

+0

我認爲OP需要每個sensorID的最新版本。 – malhal