2

アプリケーションにいくつかのカウンターを実装しようとしているときに、この奇妙な動作に遭遇しました。基本的に、私はカウンターテーブルを次のようにしました:

CREATE TABLE stats_dev.log_counters (
  date text PRIMARY KEY,
  all counter
);

次に、カウントしたい特定の種類のメッセージがあるので、Go アプリでテーブルを ALTER して、以前にはなかった列を追加します。

私のアプリは成長しており、30 を超える列 (50 を超えるべきではありません) を持ち始めています。これらすべてのカウンターを取得したい場合、結果にいくつかの列がありません。

query := s.Query(`SELECT * FROM `+_apiCountersTable+` WHERE date IN ?`, dates)
res, err := query.Iter().SliceMap()

これは、34 列に対して 30 のようなものを返します。ただし、 CQLSH でリクエストを行うと:

cqlsh:stats_dev> SELECT * FROM api_counters WHERE date = 'total';

適切な完全な結果が得られます。そう :

  1. それは異なるはずの私の要求から来ていますか?
  2. それはgocqlドライバーから来るのでしょうか?
  3. そのパターンは完全に愚かですか?

私の一時的な解決策は、テーブルから列名を SELECT し、system.schema_columnsそのすべてを SELECT クエリに string.Join() することです...

ご助力ありがとうございます。

4

2 に答える 2

2

私は gocql ライブラリに精通していませんが、ステートメントを再準備しないこととCASSANDRA-7910の組み合わせに遭遇している可能性があるようです。

リクエストが準備されているときはいつでも (Select * from ___ where date in ? で何が行われているかのように)、そのテーブルの列メタデータで応答する cassandra にリクエストを送信します。 cassandra さん、検索できる列がわかりましたね。gocql には、Automatic query preparationリクエストを準備済みステートメントとして処理している可能性があるという機能があるようです。

テーブルを変更すると、準備されたステートメントはクライアント側で更新されないため、これを修正する唯一の方法は、ステートメントを再準備することです (gocql からそのレベルの制御があるかどうかはわかりません)。ただし、cassandra にはバグ ( CASSANDRA-7910 ) があり、新しい列を返さないため、これはまだ機能しません。これは、それ自体が側で準備済みステートメントをキャッシュし、スキーマが変更されたときにそれを無効にしないためです。この問題は 2.1.3 (近日公開予定) で修正されています。これを git の cassandra-2.1 ブランチに対して試して、問題が解決するかどうかを確認することをお勧めします。

アプリケーションの実行中にスキーマを変更することは異常なパターンではないため、これは機能するはずのシナリオですが、残念ながら機能しません。gocqlでステートメントを再準備する方法があるかどうかを調べます。

stmtsLRUcluster.go に varがあることがわかります。どういうわけかそれに到達できれば、準備されたステートメントを無効にすることができます。これを行う方法がない場合は、他のドライバーでステートメントを再度準備できるため、gocql に対して問題を開くことをお勧めします。Java ドライバーでこれを実行できることはわかっていますが、警告が表示されます。これは、gocql と他のドライバーの大きな違いであると思います。他のドライバーでは、準備済みステートメント オブジェクトを明示的に使用しますが、gocql ではライブラリで自動的に処理されます。

カサンドラのバグが未解決であるため、準備済みステートメントを使用しないようにし、代わりに次のようなクエリを作成する必要があると思います。SELECT * FROM api_counters WHERE date = 'total';

于 2015-01-19T23:46:40.167 に答える
2

アンディ、助けてくれてありがとう。

最初は、あなたが私に言ったことを考えると、テーブルを変更するときに時々更新して更新したSELCT column_name方がよいと思いました. system.schema_columns私はちょうどそれからstrings.join()私のSELECT FROM api_counters. それは機能しましたが、2 つの異なるインスタンスがあり、1 つがスキーマを更新し、もう 1 つが GET 要求を受け取った場合、これはまだ新しい列を認識していません。

そして、私は自分の考えを再編成し、明らかにそれを行う別の方法があることを発見し、このスキーマに合わせて変更するだけです: CREATE TABLE stats_dev.api_counters ( date text, description text, all counter, PRIMARY KEY (date, description) ); そして、私が期待している説明に基づいてフィールドを更新しています. ここまでは順調ですね。

私はそれが間違いなくオプション 3 であることを知っていました: 私のパターンは最良のものではありませんでした.

于 2015-01-21T18:51:23.087 に答える