Cassandra:固定表格中的行数

时间:2016-05-27 09:43:59

标签: cassandra cassandra-2.2

我想创建一个具有固定行数的表(假设为N),如果添加了第N + 1行,则将删除第1行。

这是表格,我用于存储图表分析的最后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;

..以及当前的行数..

SELECT COUNT(*) FROM FROM lp_registry.best;

因此,如果count> = 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.

你能指出我正确的解决方案吗?

1 个答案:

答案 0 :(得分: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);

这些是以下代码中使用的语句:

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);

Java解决方案:

// 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));