我想比较单个节点上 PostgreSQL 和 Cassandra 之间的读取性能。
我有一个包含8列,150000行的表。为了将它转换为列族,我将主键设为Cassandra中的行键,其余列与PostgreSQL中的一样。此外,我将数据批量加载到Cassandra SSTables中,因此两者的数据都在磁盘上。
从PostgreSQL中读取表格:
select * from tableName;
花费200毫秒左右。
要读取列系列(启用了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.这对我来说很重要。
感谢。
答案 0 :(得分:1)
这不是Cassandra的有效测试,因为Postgres和Cassandra不是为解决同样的问题而设计的。完整的CF扫描不是真实的查询,如果你在生产系统中这样做,你可以使用Hadoop而不是Thrift。用于检索大量数据的更真实的Cassandra测试将是一个列切片,您可以在其中检索给定密钥集的从A到n的列范围。对于Cassandra来说,这是一种更高效的操作和更合适的数据模型选择。此外,没有人在单个节点上运行Cassandra; 3个节点是最低配置。
如果你想测试全扫描功能,使用Thrift(在你的情况下通过CQL)不是这样做的,因为所有的结果都必须适合RAM并且一次通过线路序列化(即有没有游标)。如果您的所有数据都适合RAM,那么Cassandra就不适合您。通过使用Hadoop和Cassandra,您可以并行化完整扫描并在几秒钟内回答有关理论上无限量数据的问题 - 这是Postgres无法做到的。如果您想详细了解其工作原理,请查看Cassandra的Hadoop包中的RangeClient
。还值得注意的是,完整扫描需要磁盘读取,而许多常见的读取模式使用缓存而从不打磁盘。
相比之下,Cassandra在列范围查询或逐个密钥查询方面非常快。这是因为键被散列到特定节点,然后在写入时按列名排序。因此,如果你知道你的密钥和/或想要一系列连续的列(一种非常常见的Cassandra读取模式),你最好得到顺序I / O和最好的缓存数据 - 没有锁定或间接(即索引)。 / p>
答案 1 :(得分:1)
为了添加指标,我们在性能闪耀的六节点集群上运行了性能(即更多节点)。我们使用PlayOrm的可伸缩SQL运行并查询符合我们标准的所有活动,并且从其中1,000,000行的表中返回100行需要60毫秒。
通常,人们页面结果因此查询前100行是更典型的网站用例。其他自动程序“可能”获取所有行但通常在所有行上,您需要使用map / reduce。再说一次,如果你要将CQL放到所有行中,那么你就不会做苹果对苹果了。这是你在noSQL中没有做的事情。
此外,更公平的比较是Cassandra在六个或十个节点上,而不是一个,因为它变得更快,因为磁盘是并行的,这对Postgres来说真的不可行,或者至少会在执行时遇到麻烦分布式交易。这可能更多苹果到苹果,因为你不打算在生产中使用一个节点运行Cassandra。
答案 2 :(得分:0)
Thrift和CQL-Thrift是基于RPC的,而不是基于游标的。因此,Cassandra必须将整个结果集拉入内存,然后将其转换为Thrift格式并将其发送回(仍在内存中)。
所以,我有根据的猜测是,大多数差异来自于你从JVM的分配/ GC子系统中解脱出来。