2016-05-27 1 views
1

N + 1行目が追加された場合、1行目が削除される固定数の行(Nと言うことができます)のテーブルを作成します。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:

が毎回新しい結果が

SELECT wid, id FROM lp_registry.best LIMIT 1; 

..asならびに行の現在の数..最も古い行のIDが取得され、追加させたいです..

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; 

このアプローチでは、最初の選択が次のバッチと共にアトミックな操作ではないという問題があります。したがって、他のワーカーが選択とバッチの間で最も古い行を削除した場合、または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つ:なぜこれが必要ですか?たぶん、あなたのユースケースにとっては、他のアプローチが良い選択肢かもしれません。 –

+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)); 
関連する問題