web-dev-qa-db-ja.com

Cassandra CQLの句と句の場所

私はNoSQLデータベースが初めてで、Apache Cassandraを使い始めたばかりです。 「empno」列に主キーを持つ単純なテーブル「emp」を作成しました。これは、Oracleのデフォルトのscottスキーマを常に使用する単純なテーブルです。

COPYコマンドを使用してデータをロードし、クエリSelect * from emp order by empnoを発行しましたが、CQLがempno列(PK)でOrder byを許可しないことに驚いていました。また、Where条件を使用した場合、それはempno列での不等式操作を許可しませんでした(EQまたはIN条件のみが許可されると言われていました)。また、PKでは使用されておらず、インデックスもないため、他の列でのWhereおよびOrde​​r byも許可されていませんでした。

テーブル内でempnoを一意に保ち、クエリ結果をempnoのソート順にしたい場合は、誰かが私に何をすればいいですか?

(私のバージョンは:

cqlsh:demodb> show version [cqlsh 5.0.1 | Cassandra 2.2.0 | CQL spec 3.3.0 | Native protocol v4]

10
Amir S Siddiqui

Cassandraの主キーには2つの部分があります。

  • パーティションキー
  • クラスタリングキー

PRIMARY KEY (partitionKey1,clusteringKey1,clusteringKey2)

または

PRIMARY KEY ((partitionKey1,partitionKey2),clusteringKey1,clusteringKey2)

パーティションキーは、データが保存されるノードを決定します。クラスタリングキーは、パーティションキー内のデータの順序を決定します。

CQLでは、ORDER BY句は実際には、クラスター化順序の定義されたソート方向をにするためにのみ使用されます。列自体については、テーブルの作成時にCLUSTERING ORDER BY句で定義された列(およびその正確な順序...スキップなし)のみを指定できます。したがって、クエリ時に結果セットを順序付けるために任意の列を選択することはできません。

Cassandraは、クラスター化キーを使用してディスク上のデータをソートすることによりパフォーマンスを実現します。これにより、1回の読み取りでランダムな読み取りではなく、順序付けられた行のみが返されます。これが、Cassandraでクエリベースのモデリングアプローチ(多くの場合、データを複数のクエリテーブルに複製する)を取る必要がある理由です。事前にクエリを把握し、それらを提供するテーブルを作成します。

Select * from emp order by empno;

まず、WHERE句が必要です。リレーショナルデータベースを使用している場合は、それなしでクエリを実行してもかまいません。 Cassandraでは、バインドされていないSELECTクエリを回避するために最善を尽くす必要があります。さらに、Cassandraはパーティション内のソート順のみを強制できますなので、WHERE句なしでクエリを実行してもデータは返されませんとにかく、好きな順番で。

次に、前述のとおり、クラスタリングキーを定義する必要があります。結果セットをempnoで並べ替える場合は、パーティションキーとして定義する別の列を見つける必要があります。次のようなものを試してください:

CREATE TABLE emp_by_dept (
  empno text,
  dept text,
  name text,
  PRIMARY KEY (dept,empno)
) WITH CLUSTERING ORDER BY (empno ASC);

これで、部門ごとに従業員にクエリを実行できるようになり、empnoの順序で返されます。

SELECT * FROM emp_by_dept WHERE dept='IT';

ただし、明確にするために、テーブル内のすべての行をクエリしてできないことができ、単一の列で順序付けすることができます。結果セットに意味のある順序を付ける唯一の方法は、まずビジネスケースに適した方法でデータを分割することです。バインドされていないSELECTを実行すると、すべての行が返されます(クラスター内のすべてのノードに対してクエリを実行しようとしたときにクエリがタイムアウトしない場合)、結果セットの順序はパーティション内でのみ適用できます。したがって、それが意味をなすようにするには、パーティションキーで制限する必要があります。

自己宣伝をお詫びしますが、昨年、DataStaxの記事 We Shall Have Order! を書いて、これらの種類の問題を解決する方法を説明しました。それを読んで、それが役立つかどうかを確認してください。

追加の質問のために編集します。

あなたの答えから、私はカサンドラについて2つのことを結論付けました:

(1)一意として定義された列による順序のみである結果セットを取得する方法はありません。

(2)PK(partition-key + clustering-key)を定義すると、結果は常に、任意の固定パーティションキー内のクラスタリング列によって順序付けされます(1つのパーティションキー値に制限する必要があります)。 ORDER BY句が必要です。これは、行の順序(行が実際に格納される順序)を変更できないためです。つまり、Order Byは無意味です。

1)Cassandraのすべてのプライマリキーは一意です。パーティションキーで結果セットを並べ替える方法はありません。この例では、empnoで並べ替えます(deptでパーティション化した後) )–アーロン1時間前

2)ORDER BYは役に立たないと言ってしまうのを止めて、ASCとDESCの間で並べ替えの方向を切り替えることだけが実際に使用されると言います。

「emp」テーブルの「empno」列にインデックスを作成しましたが、ORDER BY empnoはまだ許可されていません。それで、インデックスは何のためのものですか?それらは、インデックスキーの特定の値のレコードを検索するためだけのものですか?

インデックス付きの列で結果セットを並べ替えることはできません。セカンダリインデックスは(対応するリレーショナルインデックスと同じではありません)、エッジケースの分析ベースのクエリにのみ役立ちます。それらはスケーリングしないため、一般的な推奨事項はセカンダリインデックスを使用しないことです。

わかりました、つまり、1つのテーブルを使用して、異なる条件と異なる並べ替え順序で異なる結果セットを取得することはできません。

正しい。

したがって、新しい要件ごとに、新しいテーブルを作成する必要があります。 ITは、テーブル(たとえば、Salesテーブル)に10億行があり、売上の合計が必要な場合(1)製品ごと、(2)リージョンごとに、これらの10億行すべてを1つの2つのテーブルに複製します。製品のクラスタリング順、リージョンのクラスタリング順。そして、Salesman_idあたりの売上高を合計する必要がある場合でも、3番目のテーブルを作成し、これらすべての10億行を再度配置しますか?それは賢明ですか?

それがいかに賢明かを決めるのはあなた次第です。しかし、クエリの柔軟性の欠如は、Cassandraの欠点です。それを回避するために、クエリテーブルを作成し続けることができます(つまり、パフォーマンスとディスクを交換します)。しかし、管理が困難または困難になるポイントに達した場合は、Cassandraが本当に適切なソリューションであるかどうかを検討するときがきました。

EDIT 20160321

こんにちはアーロン、あなたは上記のように言った "ORDER BYは役に立たないと言うのを止めるのではなく、ASCとDESCの間で並べ替えの方向を切り替えることだけが実際の用途だと言っておく"

しかし、それでも正しくないことがわかりました。 Cassandraは、CREATE TABLEの "CLUSTERING ORDER BY"カルスで定義したのと同じ方向でのみORDER byを許可します。その句でASCを定義すると、ASCによる順序のみが許可されますその逆。

エラーメッセージが表示されない場合、そのメッセージについて何を伝えればよいかを知るのは困難です。パーティションに格納されている行が多すぎると、ORDER BYを使用したクエリが失敗することを聞きました。

ORDER BYは、並べ替えに複数の列を指定した場合にも少し奇妙に機能します。 2つのクラスタリング列を定義している場合、最初の列でORDER BYを無差別に使用できます。しかし、2番目の列をORDER BY句に追加するとすぐに、bothソート方向を(CLUSTERING ORDER BYと同じように)指定した場合にのみクエリが機能します定義)または両方異なる。私が混ぜて一致させると、これが得られます:

InvalidRequest: code=2200 [Invalid query] message="Unsupported order by relation"

データがディスクに保存される方法に関係していると思います。そうでない場合、Cassandraは、結果セットの準備でさらに多くの作業が必要になります。CLUSTERING ORDER BYで指定された方向と一致またはミラーリングするためにすべてが必要な場合、ディスクからのシーケンシャル読み取りをリレーするので、より予測可能な結果を​​得るには、ORDER BY句で単一の列のみを使用するのがおそらく最善です。

24
Aaron

受け入れられた回答としてのredux回答の追加は非常に長いです。

Order byは現在、PRIMARY KEYのクラスター化された列で、パーティションキーがwhere句のEqualityまたはIN演算子によって制限されている場合にのみサポートされています。

これは、主キーが次のように定義されている場合です。

PRIMARY KEY ((a,b),c,d)

次に、クエリが次の場合にのみ、ORDER BYを使用できます。

すべての主キーが等号演算子(=)または次のようなIN演算子によって制限されているwhere句:

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c,d;

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c;

これら2つのクエリのみが有効です。

また、このクエリは機能しません:

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY d,c;

現在、order byは、主キー定義cにあるPRIMARY KEYで宣言された順序に続く列の順序のみをサポートしているため、dの前にcが宣言されており、クエリはdを最初に置くことによって順序に違反しています。

1
Sankar