优化子句查询卡桑德拉?
optimize in clause queries cassandra?
我在 Scylladb 中有一个这样的 table。为了清楚起见,我从 table 下面删除了很多列,但总的来说,这个 table 总共有 ~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
子句似乎不好,所以有什么方法可以针对我的查询模式优化我的 table 或者 Cassandra/Scylladb 不是好的用例吗?
- 我们使用 C# 驱动程序执行上述查询,我们发现数据模型和查询模式存在性能问题。执行单个客户端 ID 异步是否更好,还是我应该继续使用其中的所有 clientId 进行
IN
子句查询?
我们 运行 6 个节点集群都在一个 DC 中,RF 为 3。我们 read/write 作为本地仲裁。
当你在分区键上发出IN
时,然后请求被发送到协调器节点(我不记得了,我认为在这种情况下,它可能是一个任意节点),然后是协调器节点将此 IN
分解为对各个分区的查询,对特定副本执行查询,收集数据并发送给调用者。所有这些导致协调器节点和副本之间的额外往返,以及对协调器的额外负载。
通常,更好的解决方案是对 IN
列表中的每个分区发出 N 个异步查询,并在客户端收集数据 - 当您使用准备好的语句时,驱动程序将能够使用令牌感知负载平衡,并将查询直接发送到持有给定分区的副本,因此您可以避免协调器和副本之间的额外网络往返。
IN 查询的问题有两个。首先是另一个答案中提到的往返问题,即协调器可能不会同时是所有请求的副本。第二个问题是过度读取:在将读取请求分派给副本时,协调器无法知道每个分区有多少数据。因此,为了确保页面将被填充,它从每个分区请求一页数据。如果每个或大多数分区都有大量数据,这将导致返回过多数据并且其中大部分被丢弃,因为它不适合页面。在下一页,大部分数据将被读取并可能再次被丢弃。
我在 Scylladb 中有一个这样的 table。为了清楚起见,我从 table 下面删除了很多列,但总的来说,这个 table 总共有 ~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
子句似乎不好,所以有什么方法可以针对我的查询模式优化我的 table 或者 Cassandra/Scylladb 不是好的用例吗? - 我们使用 C# 驱动程序执行上述查询,我们发现数据模型和查询模式存在性能问题。执行单个客户端 ID 异步是否更好,还是我应该继续使用其中的所有 clientId 进行
IN
子句查询?
我们 运行 6 个节点集群都在一个 DC 中,RF 为 3。我们 read/write 作为本地仲裁。
当你在分区键上发出IN
时,然后请求被发送到协调器节点(我不记得了,我认为在这种情况下,它可能是一个任意节点),然后是协调器节点将此 IN
分解为对各个分区的查询,对特定副本执行查询,收集数据并发送给调用者。所有这些导致协调器节点和副本之间的额外往返,以及对协调器的额外负载。
通常,更好的解决方案是对 IN
列表中的每个分区发出 N 个异步查询,并在客户端收集数据 - 当您使用准备好的语句时,驱动程序将能够使用令牌感知负载平衡,并将查询直接发送到持有给定分区的副本,因此您可以避免协调器和副本之间的额外网络往返。
IN 查询的问题有两个。首先是另一个答案中提到的往返问题,即协调器可能不会同时是所有请求的副本。第二个问题是过度读取:在将读取请求分派给副本时,协调器无法知道每个分区有多少数据。因此,为了确保页面将被填充,它从每个分区请求一页数据。如果每个或大多数分区都有大量数据,这将导致返回过多数据并且其中大部分被丢弃,因为它不适合页面。在下一页,大部分数据将被读取并可能再次被丢弃。