2

geohash で行を取得できるようにする必要がある cassandra テーブルを設計しています。機能するものがありますが、現在できる以上に範囲クエリを避けたいと思います。

現在のテーブル スキーマはこれで、geo_key には geohash 文字列の最初の 5 文字が含まれています。geo_key を使用してクエリを実行し、完全な geohash で範囲フィルターを使用して、5 つ以上の長さの geohash に基づいてプレフィックス検索を実行できるようにします。

CREATE TABLE georecords (geo_key text,geohash text, data text) PRIMARY KEY (geo_key, geohash))

私の考えは、代わりにジオハッシュの文字を個別の列として保存し、必要な数の文字を指定して、ジオハッシュでプレフィックスマッチを実行できるようにすることです。私の懸念は、複数のクラスタリング列を使用した場合の影響です。

CREATE TABLE georecords (g1 text,g2 text,g3 text,g4 text,g5 text,g6 text,g7 text,g8 text,geohash text, data text) PRIMARY KEY (g1,g2,g3,g4,g5,g6,g7,g8,geohash,pid))

(パーティションキーのカーディナリティについてはあまり心配していません-g1には最小30の値があり、他の回避策もあります)

パーティション キーのカーディナリティと追加のストレージ要件以外に、多数のクラスター列のアプローチを使用した場合、何に注意する必要がありますか?

4

2 に答える 2

3

パーティション キーのカーディナリティと追加のストレージ要件の他に、多数のクラスター列のアプローチを使用した場合、何に注意する必要がありますか?

これは興味深い問題のように思えたので、異なる PRIMARY KEY 構造とオプションの CQL テーブルをいくつか作成しました。次に、 http: //geohash.org/を使用していくつかのエンドポイントを作成し、それらを挿入しました。

aploetz@cqlsh:stackoverflow> SELECT g1, g2, g3, g4, g5, g6, g7, g8, geohash, pid, data FROm georecords3;

 g1 | g2 | g3 | g4 | g5 | g6 | g7 | g8 | geohash      | pid  | data
----+----+----+----+----+----+----+----+--------------+------+---------------
  d |  p |  8 |  9 |  v |  c |  n |  e |  dp89vcnem4n | 1001 |    Beloit, WI
  d |  p |  8 |  c |  p |  w |  g |  v |    dp8cpwgv3 | 1003 |   Harvard, IL
  d |  p |  c |  8 |  g |  e |  k |  t | dpc8gektg8w7 | 1002 | Sheboygan, WI
  9 |  x |  j |  6 |  5 |  j |  5 |  1 |    9xj65j518 | 1004 |    Denver, CO

(4 rows)

ご存じのとおり、Cassandra は、特定の正確なキーでデータを返すように設計されています。複数のクラスタリング列を使用すると、Cassandra が取得したいデータをすばやく特定できるようになるという点で、そのアプローチに役立ちます。

変更について私が考える唯一のことは、PRIMARY KEY なしで、geohashまたはpidPRIMARY KEY でできるかどうかを確認することです。pid私の腸は、実際にはクエリを実行するものではないため、を取り除くように言っています。それが提供する唯一の価値は、同じジオハッシュを複数回保存することを計画している場合に必要になる一意性です。

PRIMARY KEY に含めると、キー以外の列が 1 つ残り、ディレクティブpidを使用できるようになります。WITH COMPACT STORAGE実際にあなたを得る唯一の真の利点は、クラスタリング列名が値とともに保存されないため、ディスク領域を節約することです。cassandra-cliこれは、ツール内からテーブルを見ると明らかになります。

コンパクト収納なし:

[default@stackoverflow] list georecords3;
Using default limit of 100
Using default cell limit of 100
-------------------
RowKey: d
=> (name=p:8:9:v:c:n:e:dp89vcnem4n:1001:, value=, timestamp=1428766191314431)
=> (name=p:8:9:v:c:n:e:dp89vcnem4n:1001:data, value=42656c6f69742c205749, timestamp=1428766191314431)
=> (name=p:8:c:p:w:g:v:dp8cpwgv3:1003:, value=, timestamp=1428766191382903)
=> (name=p:8:c:p:w:g:v:dp8cpwgv3:1003:data, value=486172766172642c20494c, timestamp=1428766191382903)
=> (name=p:c:8:g:e:k:t:dpc8gektg8w7:1002:, value=, timestamp=1428766191276179)
=> (name=p:c:8:g:e:k:t:dpc8gektg8w7:1002:data, value=536865626f7967616e2c205749, timestamp=1428766191276179)
-------------------
RowKey: 9
=> (name=x:j:6:5:j:5:1:9xj65j518:1004:, value=, timestamp=1428766191424701)
=> (name=x:j:6:5:j:5:1:9xj65j518:1004:data, value=44656e7665722c20434f, timestamp=1428766191424701)

2 Rows Returned.
Elapsed time: 217 msec(s).

コンパクトな収納:

[default@stackoverflow] list georecords2;
Using default limit of 100
Using default cell limit of 100
-------------------
RowKey: d
=> (name=p:8:9:v:c:n:e:dp89vcnem4n:1001, value=Beloit, WI, timestamp=1428765102994932)
=> (name=p:8:c:p:w:g:v:dp8cpwgv3:1003, value=Harvard, IL, timestamp=1428765717512832)
=> (name=p:c:8:g:e:k:t:dpc8gektg8w7:1002, value=Sheboygan, WI, timestamp=1428765102919171)
-------------------
RowKey: 9
=> (name=x:j:6:5:j:5:1:9xj65j518:1004, value=Denver, CO, timestamp=1428766022126266)

2 Rows Returned.
Elapsed time: 39 msec(s).

ただし、次の理由から使用しないことをお勧めします。WITH COMPACT STORAGE

  • テーブルの作成後に列を追加または削除することはできません。
  • テーブルに複数の非キー列が含まれないようにします。
  • これは、列ファミリー (テーブル) モデリングに対する古い (非推奨の) 倹約ベースのアプローチで使用することを実際に意図しており、実際には使用/不要になりました。
  • はい、ディスク容量を節約できますが、ディスク容量は安価なので、これは非常に小さな利点だと思います。

「パーティションキーのカーディナリティ以外」と言ったのは知っていますが、とにかくここで言及します。dサンプル データ セットを見ると、ほぼすべての行がパーティション キーの値と共に格納されていることがわかります。ウィスコンシン州/イリノイ州のステートライン エリアで geohash を追跡するこのようなアプリケーションを自分で作成するとしたら、ほとんどのデータが同じパーティションに格納される (クラスター内にホットスポットを作成する) という問題が発生することは間違いありません。したがって、ユース ケースと潜在的なデータを知っていれば、おそらく最初の 3 つほどの列を 1 つのパーティション キーに結合します。

すべてを同じパーティション キーに格納する場合のもう 1 つの問題は、各パーティションに最大で約 20 億列を格納できることです。したがって、データがそのマークを超える可能性があるかどうかにかかわらず、いくつかのことを後回しにすることも理にかなっています. そして明らかに、パーティション キーのカーディナリティが高いほど、この問題に遭遇する可能性は低くなります。

あなたの質問を見ると、あなたは自分のデータを見て、この...明確な「プラス」を理解しているように見えます。また、パーティション キーに 30 個の一意の値があれば、十分な分散が提供されます。私は、それがどれほど大きな取引になるかを説明するのに少し時間を費やしたかっただけです.

とにかく、あなたが正しい軌道に乗っているように聞こえるので、「うまくやった」ことも追加したかった.

編集

私にとってまだ解決されていない問題は、どのアプローチがどのような状況でより適切にスケーリングするかということです。

スケーラビリティは、N ノードにまたがる R レプリカの数にさらに関係しています。Cassandra は直線的にスケーリングします。追加するノードが多いほど、アプリケーションが処理できるトランザクションが増えます。純粋にデータ分散のシナリオから、最初のモデルのパーティション キーのカーディナリティが高くなるため、2 番目のモデルよりもはるかに均等に分散されます。ただし、最初のモデルは、クエリの柔軟性に関して、より制限的なモデルを提示します。

さらに、パーティション内で範囲クエリを実行している場合 (そう言ったと思います)、2 番目のモデルは非常にパフォーマンスの高い方法でそれを可能にします。パーティション内のすべてのデータは同じノードに格納されます。そのため、...etc...に対して複数の結果をクエリするg1='d' AND g2='p'と、非常にうまく機能します。

もっとデータをいじってテストケースを実行する必要があるかもしれません。

それはいい考えです。2 番目のモデルが最適な方法であることがわかると思います (クエリの柔軟性と複数行のクエリの観点から)。単一行のクエリに関して、2 つの間にパフォーマンスの違いがある場合、私の疑いでは、それは無視できるはずです。

于 2015-04-11T16:11:41.850 に答える