4

我正在使用带有 CQL3 的 cassandra 1.2。我的键空间中有三个列族。当我查询其中一个列族(电话)时,需要很长时间才能检索。这是我的查询

**select * from phones where phone_no in ('9038487582');**

这是查询的跟踪输出。

activity                                        | timestamp    | source      | source_elapsed
-------------------------------------------------+--------------+-------------+----------------
                              execute_cql3_query | 16:35:47,675 | 10.1.26.155 |              0
                               Parsing statement | 16:35:47,675 | 10.1.26.155 |             58
                              Peparing statement | 16:35:47,675 | 10.1.26.155 |            335
      Executing single-partition query on phones | 16:35:47,676 | 10.1.26.155 |           1069
                    Acquiring sstable references | 16:35:47,676 | 10.1.26.155 |           1097
                       Merging memtable contents | 16:35:47,676 | 10.1.26.155 |           1143
 Partition index lookup complete for sstable 822 | 16:35:47,676 | 10.1.26.155 |           1376
 Partition index lookup complete for sstable 533 | 16:35:47,686 | 10.1.26.155 |          10659
      Merging data from memtables and 2 sstables | 16:35:47,704 | 10.1.26.155 |          29192
              Read 1 live cells and 0 tombstoned | 16:35:47,704 | 10.1.26.155 |          29332
                                Request complete | 16:35:47,704 | 10.1.26.155 |          29601

我在键空间上只有 1 个复制因子。并拥有 3 个节点集群。电话有大约 4000 万行,每行只有两列。它在 29 毫秒、15 毫秒、8 毫秒、5 毫秒、3 毫秒内返回,但并不一致。你们能就我可能犯的错误给我任何建议吗?此外,我的用例缓存命中率极低,因此缓存密钥对我来说不是解决方案。另外,这是我的列族定义。

CREATE TABLE phones (
  phone_no text PRIMARY KEY,
  ypids set<int>
) WITH
  bloom_filter_fp_chance=0.100000 AND
  caching='KEYS_ONLY' AND
  comment='' AND
  dclocal_read_repair_chance=0.000000 AND
  gc_grace_seconds=864000 AND
  read_repair_chance=0.100000 AND
  replicate_on_write='true' AND
  populate_io_cache_on_flush='false' AND
  compaction={'class': 'LeveledCompactionStrategy'} AND
  compression={'sstable_compression': 'SnappyCompressor'};
4

3 回答 3

4

索引查找相当快(索引文件可能正在被操作系统缓存,因为它被频繁访问);你一直在丢失的地方是在这和“合并数据”步骤之间。在这两者之间发生的实际上是寻找 sstable 中的数据位置。(我为 1.2.6 添加了一个新的跟踪条目以明确这一点。)

这就解释了为什么有时它很快,有时又不是——如果你的搜索没有争议,或者更好的是缓存,那么查询会很快。否则会比较慢。

我看到了几个可以提供帮助的选项:

  1. 切换到分级压缩 ( http://www.datastax.com/dev/blog/when-to-use-leveled-compaction )
  2. 添加更多机器以通过蛮力获得更多 iops
  3. 切换到 SSD 以通过更好的硬件获得更多 iops
  4. 添加更多 RAM 以使缓存更有效地掩盖 iops 的不足

您会注意到,只有第一个选项不包含更多或不同的硬件,所以这是我首先要评估的。但好处是有限的:充其量你会将 sstables 的数量减少到 1。

于 2013-05-23T18:14:23.053 回答
3

从您在上面提供的表中,大部分查询时间都在索引查找和合并 SSTables 中。这是相当普遍的,我不相信你做错了什么。

可以通过对数据进行反规范化来避免索引查找。Cassandra 的常见做法是围绕查询设计 ColumnFamilies,而不是关系系统中典型的表。然后,这将负担放在写入数据的点上,这是 Cassandra 最强大的地方,当然,由于数据重复和 cassandra 为客户提供不同数据视图以优化数据的集群可用性而存在数据一致性风险.

sstables 的合并可以说是 Cassandra 的致命弱点。Cassandra 以牺牲读取时间延迟和延迟一致性为代价来优化写入速度和可靠性。Cassandra 的“较慢”读取持续时间不断变化是完全正常的。为了减少这个问题,有两种方法,第一种是避免对列族中的数据进行任何类型的更新或删除,因为这会导致稍后进行压缩。但即便如此,这也只会延迟 sstable 的工作,因为插入会导致内存表被刷新。因此,如果变化/持续时间仍然太长,可以考虑的另一个解决方案是在 Cassandra 前面使用缓存,例如 Memcache。这是 Netflix 在此处记录的方法Netflix benchmarking of Cassandra

为了完整起见,我应该补充一点,Cassandra 中的列族设置可以进行调整、基准测试,然后再次调整以减少此问题。但这只会解决这个问题,因为这个问题是 Cassandra 设计中固有的。您应该查看的设置是缓存大小,例如 memtables 及其溢出率,这是创建新 SSTable 的点。压缩也有帮助,因为这有助于将更多数据压缩到内存中。通常,我预计未编制索引的读取需要 2-10 毫秒(平均 5 毫秒),具体取决于 Amazon EC2(这是我目前工作的环境)中的硬件和集群活动。

于 2013-05-18T10:13:09.220 回答
1

Cassandra 查询通常非常快,并且通常需要固定的时间。如果您对列族的单个列进行查询,与对所有列进行查询相比,返回需要多少时间?一些开销预计会导致更多列,但不会太多,例如大约 1 或 2 毫秒。

如果查询全部和查询单行之间存在很大差异(超过两倍),即使列族中没有太多数据,也可能您的查询构造不正确。如果您希望一行中有可预测的列,您可以尝试将它们一起查询,而不是使用通配符进行查询。它可能会对查询的速度产生巨大的影响。

于 2013-05-18T10:57:56.853 回答