3

単一ノードでPostgreSQLCassandra の読み取りパフォーマンスを比較したい。

8 列、150000 行のテーブルがあります。列ファミリーに変換するために、主キーを Cassandra の行キーにし、残りの列は PostgreSQL と同じです。また、両方のデータがディスク上にあるように、データを Cassandra SSTables に一括ロードしました。

PostgreSQL からテーブルを読み取るには:

 select * from tableName;

200ms程度かかります。

列ファミリー (キーキャッシュと行キャッシュを有効にして) を読み取るために、thrift API (get_range_slices メソッド) と CQL2.0 の両方を試しました。前者は平均して約 7000 ミリ秒かかり、後者は耐え難いほど 100000 ミリ秒かかります。

Cassandra Memtables から読み取ると、かなり高速になる可能性があります。しかし、どちらもディスクから読み取るのに、なぜ Cassandra はずっと遅いのでしょうか?

根底にあるメカニズムは何ですか?

編集:

顧客列ファミリー

CREATE COLUMN FAMILY customer
WITH comparator = UTF8Type
AND key_validation_class = UTF8Type
AND caching = all
AND column_metadata = 
[
 {column_name: C_NAME, validation_class: UTF8Type},
 {column_name: C_ADDRESS, validation_class: UTF8Type},
 {column_name: C_NATIONKEY, validation_class: UTF8Type},
 {column_name: C_PHONE, validation_class: UTF8Type},
 {column_name: C_ACCTBAL, validation_class: UTF8Type},
 {column_name: C_MKTSEGMENT, validation_class: UTF8Type},
 {column_name: C_COMMENT, validation_class: UTF8Type}
];

これが私の倹約クエリです

   // customer is that column family of 150000 rows
   ColumnParent cf1 = new ColumnParent("customer");
   // all columns
   SlicePredicate predicate = new SlicePredicate();
   predicate.setSlice_range(new SliceRange(ByteBuffer.wrap(new byte[0]), ByteBuffer.wrap(new byte[0]), false, 100));
   // all keys
   KeyRange keyRange = new KeyRange(150000);
   keyRange.setStart_key(new byte[0]);
   keyRange.setEnd_key(new byte[0]);
   List<KeySlice> cf1_rows = client.get_range_slices(cf1, predicate, keyRange, ConsistencyLevel.ONE);   

また、私のCQL2.0クエリ:

   select * from customer limit 150000;

編集:

私は誤解を招くタイトルで自分を責めており、提供されたデータはさらに論争を引き起こす可能性があります. ここで勝者を選んでいるわけではありません。

どちらもディスク I/O を実行しており (これは Cassandra の一般的な使用例ではありません)、時間が異なるため、何らかの理由があるはずです。彼らがそれに対処する方法に興味があります。ですから、根底にあるメカニズムに光を当てていただければ幸いです。

これはリンゴとリンゴの比較ではありませんが、私の懸念はフレーバーです. 1 つの方が酸味が強いのは、おそらくビタミン C が多く含まれているためです。

ありがとう。

4

3 に答える 3

1

Postgres と Cassandra は同じ問題に対処するように設計されていないため、これは Cassandra の有効なテストではありません。完全な CF スキャンは実際のクエリではありません。本番システムでこれを実行する場合は、Thrift ではなく Hadoop を使用して実行します。大量のデータを取得するためのより現実的な Cassandra テストは、特定のキー セットに対して A から n までの範囲の列を取得する列スライスです。これははるかに効率的な操作であり、Cassandra にとってより適切なデータ モデルの選択です。さらに、単一のノードで Cassandra を実行する人はいません。3 ノードは最低限の構成です。

フルスキャン機能をテストしたい場合、Thrift を使用して (あなたの場合は CQL を介して) 行う方法ではありません。すべての結果が RAM に収まり、ワイヤ上で一度にシリアル化される必要があるためです (つまり、カーソルはありません)。 . すべてのデータが RAM に収まる場合、Cassandra は適切な選択ではありません。Cassandra で Hadoop を使用すると、フル スキャンを並列化し、理論的に無限の量のデータに関する質問に数秒で答えることができます。これは、Postgres が行うようには設計されていません。これがどのように機能するかを詳しく知りたい場合はRangeClient、Cassandra の Hadoop パッケージにある を調べてください。また、フル スキャンにはディスクの読み取りが必要であるのに対し、多くの一般的な読み取りパターンではキャッシュが使用され、ディスクにヒットすることはありません。

対照的に、Cassandra は列範囲クエリまたはキーによる取得で非常に高速です。これは、キーが特定のノードにハッシュされ、書き込み時に列名でソートされるためです。したがって、キーがわかっている場合や連続した列の範囲が必要な場合 (非常に一般的な Cassandra 読み取りパターン)、最悪の場合はシーケンシャル I/O が得られ、最良の場合はキャッシュされたデータが得られます。ロックや間接化 (つまりインデックス) はありません。

于 2012-09-27T13:28:14.290 に答える
1

メトリックを追加するために、パフォーマンスが優れている (つまり、より多くのノード) 6 ノード クラスターでパフォーマンスの実行を行いました。PlayOrm のスケーラブル SQL を実行し、条件に一致するすべてのアクティビティをクエリしました。1,000,000 行のテーブルから 100 行を返すのに 60 ミリ秒かかりました。

一般的に、ピープル ページの結果なので、最初の 100 行のクエリは、より一般的な Web サイトのユース ケースです。他の自動化されたプログラムはすべての行を「取得する可能性があります」が、通常はすべての行で map/reduce を使用する必要があります。繰り返しになりますが、noSQL では行わないすべての行に CQL を実行する場合、りんごとりんごを行っているわけではありません。

また、より公平な比較は、1 つではなく 6 つまたは 10 個のノードの Cassandra です。ディスクが並列であるため高速になるため、Postgres では実際に実行できないこと、または少なくとも分散トランザクションの実行に問題が発生する可能性があります。Cassandra を実稼働環境で 1 つのノードで実行するつもりはないため、これは同じことかもしれません。

于 2012-09-27T18:53:17.620 に答える
0

ThriftおよびCQL-over-Thriftは、カーソルベースではなくRPCベースです。そのため、Cassandraは結果セット全体をメモリにプルし、それをThrift形式に変換して、(メモリ内に)送り返す必要があります。

ですから、私の知識に基づく推測では、違いのほとんどは、JVMの割り当て/GCサブシステムから地獄を破壊することとの違いです。

于 2012-09-28T19:17:59.693 に答える