【问题标题】:How Cassandra deals with disk IOCassandra 如何处理磁盘 IO
【发布时间】:2012-10-09 16:02:57
【问题描述】:

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

谢谢。

【问题讨论】:

  • 你能发布你的节俭查询吗?有时查询可能会以非常低效的方式编写。
  • @baba 我已经发布了查询
  • Cassandra 通常对可变长度键执行键范围查询非常慢。您还可以发布您的列族定义吗?您使用 BytesType 比较器吗?另外,您是否尝试过使用 keyRange.setEnd_key(Bytes.fromLong(Long.MAX_VALUE).getBytes());代替你的结束键的新字节[0]?
  • @baba setEnd_key 这样会返回错误的结果
  • 这是为什么呢?我假设你的键是长的,所以如果你使用的是 BytesType 比较器,那么你的 keyRange 可以从 0 开始到最大值。

标签: postgresql io cassandra


【解决方案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 并在最好的情况下获得缓存数据——没有锁定或间接(即索引)。

【讨论】:

  • 我并不是说 Cassandra 做得不好。我想知道的是两者如何分别处理磁盘 IO。另外,我的兴趣不在于 Cassandra 已经拥有的东西,而是它缺少的东西。 Cassandra 现在支持对值的查询,并提供了早期版本的 Cassandra 无法做到的 SQL 接口
  • 我听到你在说什么,但问题是两者存储数据的方式不同。 Postgres 中的表扫描与 Cassandra 中的 CF 扫描不同的磁盘访问模式。如果您想将苹果与磁盘 I/O 上的苹果进行比较,请使用可比较的测试。
  • 是的,这就是我想知道的。表扫描与 CF 扫描有何不同。
  • 但问题是为什么?您想对两者进行基准测试,大概是因为您有一些要尝试解决的用例并想知道哪个更快/更好。我认为您应该提出适合每个解决方案的特定基准和数据/查询模型。
  • 是的,我愿意。我想在 Cassandra 之上添加加入。据我所知,没有像 NoSQL 数据库中的基准连接这样的基准
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    所以,我有根据的猜测是,大部分区别在于您彻底摆脱了 JVM 的分配/GC 子系统。

    【讨论】:

    • 如果我直接在StorageProxy这样的接口上工作,我是否会获得与在Postgres中类似的体验
    猜你喜欢
    • 2013-11-21
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多