我想创建一个具有固定行数的表(假设为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.
你能指出我正确的解决方案吗?
答案 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));