Cassandra如何处理磁盘IO



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

我有一张8列150000行的表格。为了将其转换为列族,我将主键设置为Cassandra中的行键,其余列与PostgreSQL中的列相同。此外,我将数据大容量加载到Cassandra SSTables中,以便两者的数据都在磁盘上。

从PostgreSQL读取表:

select * from tableName;

大约200毫秒。

为了读取列族(启用了keycache和rowcache),我尝试了rift API(get_range_slices方法)和CQL2.0。前者平均耗时约7000毫秒,后者则高达10万毫秒。

我知道如果读《卡桑德拉回忆录》的话可能会很快。但既然他们都是从磁盘上读取的,为什么卡桑德拉要慢得多?

哪些潜在机制至关重要?

编辑:

客户列系列

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。这对我来说很重要。

谢谢。

这对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,最好的情况是缓存数据——没有锁定或间接(即索引)。

为了增加您的指标,我们在一个性能出众的六节点集群上进行了性能运行(即更多节点)。我们使用PlayOrm的可伸缩SQL运行,并查询所有符合我们标准的活动,从其中1000000行的表中返回100行需要60毫秒。

一般来说,人员页面的结果,所以查询前100行是一个更典型的网站用例。其他自动化程序"可能"会获取所有行,但通常在所有行上,您需要使用map/reduce。同样,如果您要将CQL放入所有行,那么您就不是在逐个执行,而这是noSQL中没有做的。

此外,一个更公平的比较是Cassandra在六个或十个节点上,而不是一个,因为由于磁盘是并行的,它会变得更快,这对Postgres来说是不可行的,或者至少在执行分布式事务时会遇到困难。这可能是更多的苹果对苹果,因为你不会在生产中用一个节点运行Cassandra。

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

因此,我有根据的猜测是,大部分区别都来自于你对JVM的分配/GC子系统的彻底破坏。

最新更新