3

我想在单个节点上比较PostgreSQLCassandra 之间的读取性能。

我有一个 8 列、150000 行的表。要将其转换为列族,我将主键设置为 Cassandra 中的行键,其余列与 PostgreSQL 中的一样。此外,我将数据批量加载到 Cassandra SSTables 中,因此两者的数据都在磁盘上。

从 PostgreSQL 读取表:

 select * from tableName;

它花费200ms左右。

为了读取列族(启用了 keycache 和 rowcache),我尝试了 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 的典型用例)并且他们的时间不同,所以必须有一个原因。我很好奇他们处理这个问题的方式。因此,如果你们对底层机制有所了解,我将不胜感激。

这不是苹果对苹果的比较,但我担心的是味道。一个更酸可能是因为它含有更多的维生素 C。这对我来说很重要。

谢谢。

4

3 回答 3

1

为了增加您的指标,我们在性能表现出色的六节点集群(即更多节点)上进行了性能运行。我们使用 PlayOrm 的 Scalable SQL 运行并查询所有符合我们条件的 Activite,从包含 1,000,000 行的表中返回 100 行需要 60 毫秒。

通常,人员页面结果因此查询前 100 行是更典型的网站用例。其他自动化程序“可能”获取所有行,但通常在所有行上,您需要使用 map/reduce。同样,如果您将 CQL 用于所有行,那么您不是在做苹果对苹果的事,而这是您在 noSQL 中不做的事情。

此外,更公平的比较是 Cassandra 在 6 个或 10 个节点上,而不是一个,因为磁盘是并行的,它变得更快,这在 Postgres 中确实不可行,或者至少在执行分布式事务时会遇到问题。这可能是更多的苹果对苹果,因为您不会在生产中使用一个节点运行 Cassandra。

于 2012-09-27T18:53:17.620 回答
1

这不是对 Cassandra 的有效测试,因为 Postgres 和 Cassandra 并非旨在解决相同的问题。完整的 CF 扫描不是真实世界的查询,如果您在生产系统中执行此操作,您将使用 Hadoop 而不是通过 Thrift 执行此操作。用于检索大量数据的更现实的 Cassandra 测试将是列切片,其中您要检索给定键集的从 A 到 n 的列范围。这是一种更高效的操作,也是 Cassandra 更合适的数据模型选择。此外,没有人在单个节点上运行 Cassandra。3 个节点是最低配置。

如果您想测试完整扫描功能,则使用 Thrift(在您的情况下通过 CQL)不是这样做的方法,因为您的所有结果都必须适合 RAM 并立即通过网络进行序列化(即没有游标) . 如果您的所有数据都可以放入 RAM,那么 Cassandra 不是您的正确选择。将 Hadoop 与 Cassandra 结合使用可以让您在几秒钟内并行执行全面扫描并回答有关理论上无限量数据的问题——这是 Postgres 不适合做的事情。如果您想详细了解它的工作原理,请查看RangeClientCassandra 的 Hadoop 包中的内容。还值得注意的是,完全扫描需要读取磁盘,而许多常见的读取模式使用缓存并且从不命中磁盘。

相比之下,Cassandra 在列范围查询或按键获取方面非常快。这是因为键被散列到特定节点,然后在写入时按列名排序。因此,如果您知道您的键和/或想要一系列连续的列(一种非常常见的 Cassandra 读取模式),那么您在最坏的情况下获得顺序 I/O,而在最好的情况下获得缓存数据——没有锁定或间接(即索引)。

于 2012-09-27T13:28:14.290 回答
0

Thrift 和 CQL-over-Thrift 是基于 RPC 的,而不是基于游标的。因此 Cassandra 必须将整个结果集拉入内存,然后将其转换为 Thrift 格式并发送回(仍在内存中)。

所以,我有根据的猜测是,大部分不同之处在于你彻底摆脱了 JVM 的分配/GC 子系统。

于 2012-09-28T19:17:59.693 回答