2016-05-27 38 views
1

我想创建一个固定行数的表(可以说N),其中如果第N + 1行被添加,那么第1行将被删除。Cassandra:固定表中的行数

这是表,我用从图形分析最近的N最佳效果存储:

CREATE TABLE IF NOT EXISTS lp_registry.best (
    value float, // best value for current graph 
    verts int, // number of vertices in graph 
    edges int, // number of edges in graph 
    wid text, // worker id  
    id timeuuid, // timeuuid 
    PRIMARY KEY (wid, id) 
) WITH CLUSTERING ORDER BY (id ASC); 

我读过有关expiring data at DataStax,却发现只有TTL到期。所以我决定按照以下方式来做。

我的解决方法A:

每当有新的结果是想加入,最早的行ID检索..

SELECT wid, id FROM lp_registry.best LIMIT 1; 

..as以及行的当前号码..

SELECT COUNT(*) FROM FROM lp_registry.best; 

因此如果计数> = N,则最旧的行被移除并且最新被添加...

BEGIN BATCH 
    INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now()); 
    DELETE FROM lp_registry.best WHERE wid = ? AND id = ?; 
APPLY BATCH; 

这种方法有问题,第一个选择不是与下一批次一起的原子操作。因此,如果其他工作人员删除了select和batch之间最旧的行,或者超过了N,那么这将不起作用。

我的方法B:

相同的第一步骤...

SELECT wid, id FROM lp_registry.best LIMIT 1; 
SELECT COUNT(*) FROM FROM lp_registry.best; 

然后尝试一次又一次删除最早的行,直到成功为止..

if count < N { 
    INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now()); 
} else { 
    while not success { 
    DELETE FROM lp_registry.best WHERE wid = ? AND id = ? IF EXISTS; 
    } 
    INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now()); 
} 

在这种方法在数据库中超过N之前仍然存在问题,在检查N的数量<之前。

你能指点我一个合适的解决方案吗?

+0

一个简单的问题:你为什么需要这个?也许其他方法对你的用例来说是更好的选择。 –

+0

许多并行计算机(工作人员)对不同的数据执行相同类型的计算,计算时间差异很大。然后是一个顶级逻辑,它取N个最新结果并用它进行计算。 – Michal

回答

1

这是我的解决方案。首先,我们需要创建一个将存储行的当前号码表...

CREATE TABLE IF NOT EXISTS row_counter (
    rmax int, // maximum allowed number of rows 
    rows int, // current number of rows 
    name text, // name of table 
    PRIMARY KEY (name) 
); 

对其进行初始化对于一个给定的固定行的表:

INSERT INTO row_counter (name, rmax, rows) 
VALUES ('best', 100, 0); 

这些都在使用的语句下面的代码:Java中

q1 = "SELECT rows, rmax FROM row_counter WHERE name = 'best'"; 
q2 = "UPDATE row_counter SET rows = ? WHERE name = 'best' IF rows < ?"; 
q3 = "SELECT wid, id FROM best LIMIT 1"; 
q4 = "DELETE FROM best WHERE wid = ? AND id = ? IF EXISTS"; 
q5 = "INSERT INTO best (vertex, value, verts, edges, wid, id) VALUES (?, ?, ?, ?, ?, now())"; 

selectCounter = session.prepare(q1); 
updateCounter = session.prepare(q2); 
selectOldBest = session.prepare(q3); 
deleteOldBest = session.prepare(q4); 
insertNewBest = session.prepare(q5); 

解决方案:

// Success indicator 
boolean succ = false; 

// Get number of registered rows in the table with best results 
Row row = session.execute(selectCounter.bind()).one(); 
int rows = row.getInt("rows") + 1; 
int rmax = row.getInt("rmax"); 

// Repeatedly try to reserve empty space in table 
while (!succ && rows <= rmax) { 
    succ = session.execute(updateCounter.bind(rows, Math.min(rows, rmax))).wasApplied(); 
    rows = session.execute(selectCounter.bind()).one().getInt("rows") + 1; 
} 

// If there is not empty space in table, repeatedly try to make new empty space 
while (!succ) { 
    row = session.execute(selectOldBest.bind()).one(); 
    succ = session.execute(deleteOldBest.bind(row.getString("wid"), row.getUUID("id"))).wasApplied(); 
} 

// Insert new row 
session.execute(insertNewBest.bind(vertex, value, verts, edges, workerCode));