【问题标题】:optimize in clause queries cassandra?优化子句查询cassandra?
【发布时间】:2020-08-29 02:31:30
【问题描述】:

我在 Scylladb 中有一张这样的表。为了清楚起见,我从下表中删除了很多列,但总的来说,这张表总共有大约 25 列。

CREATE TABLE testks.client (
    client_id int,
    lmd timestamp,
    cola list<text>,
    colb list<text>,
    colc boolean,
    cold int,
    cole int,
    colf text,
    colg set<frozen<colg>>,
    colh text,
    PRIMARY KEY (client_id, lmd)
) WITH CLUSTERING ORDER BY (lmd DESC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
    AND comment = ''
    AND compaction = {'class': 'TimeWindowCompactionStrategy', 'compaction_window_size': '1', 'compaction_window_unit': 'DAYS'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 172800
    AND max_index_interval = 1024
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';

现在我们的查询模式是这样的。我的IN 子句中可以有多个50 clientIds

select * FROM testks.client WHERE client_id IN ? PER PARTITION LIMIT 1

几个问题:

  • 在线阅读后,由于明显的性能原因,IN 子句似乎不好,所以有没有办法针对我的查询模式优化我的表,或者 Cassandra/Scylladb 不是这个的好用例?
  • 我们使用 C# 驱动程序执行上述查询,我​​们发现我们的数据模型和查询模式存在性能问题。执行单个客户端 ID 异步更好还是我应该继续使用所有客户端 ID 进行 IN 子句查询?

我们在一个 DC 中运行 6 个节点集群,RF 为 3。我们作为本地仲裁进行读/写。

【问题讨论】:

    标签: database-design cassandra scylla


    【解决方案1】:

    当你在分区键上发出IN时,请求被发送到协调节点(我不记得了,我认为在这种情况下,它可能是一个任意节点),然后协调节点分解这个@987654322 @ 进入对单个分区的查询,对特定副本执行查询,收集数据并发送给调用者。所有这些都会导致协调器节点和副本之间的额外往返,以及协调器的额外负载。

    通常,更好的解决方案是为IN 列表中的每个分区发出 N 个异步查询,并在客户端收集数据 - 当您使用准备好的语句时,驱动程序将能够使用令牌感知负载平衡,并且会将查询直接发送到保存给定分区的副本,因此您可以避免协调器和副本之间的额外网络往返。

    【讨论】:

    • 感谢您的解释。所以唯一的解决方案是尝试多个异步调用,对吗?数据模型/查询模式对您来说是正确的吗?我们不能改变它来优化那个区域的任何东西吗?
    • 如果您总是查询“相关”键,数据模型更改会有所帮助。在这种情况下,您可以将它们放入单个分区等。但这需要讨论用例本身
    • 使用这种方式处理分页会不会很复杂?
    【解决方案2】:

    IN 查询的问题有两个。首先是另一个答案中提到的往返问题,即协调器可能不会也是所有请求的副本。第二个问题是过度读取:当将读取请求分派到副本时,协调器无法知道每个分区有多少数据。因此,为了确保页面将被填充,它从每个分区请求一页的数据。如果每个或大多数分区都有大量数据,这将导致返回太多数据,并且大部分数据因不适合页面而被丢弃。在下一页上,大部分数据将被读取并可能再次被丢弃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多