在Scylla中,数据是按分区键存储的。如果我查询一个有很多分区键的大表,是否相当于对该表执行多个查询?例如,假设我有下表:
key1 : val1
key2 : val2
key3 : val3
其中 3 个键 (key1..3
) 中的每一个都是不同的分区键。
如果我对表执行以下查询:
SELECT * from table.
Scylla 可能需要在 3 个不同的分区上执行此查询 3 次,因为每行都存储在不同的分区上。这看起来效率很低,因为这意味着每个分区将执行一次查询。假设数据被划分为100个分区(100个键),查询是否需要执行100次才能完成? (推而广之,查询的速度只能与最慢的服务器一样快?)
如果这是真的,那么从 3 个单独的表中查询 1 行(例如,每行具有不同的分区键)应该具有与从一个表中查询 3 行相同的性能,其中 3 个三行中的每一个都有不同的分区键分区键?换句话说,数据是否被建模为一个表或多个表的一部分并不重要。重要的是两行或多行是否共享相同的分区键?
当我们查询 3 个不同的表,每行都具有相同的分区键时,会发生什么,这与从一个表中查询 3 行(其中所有行都具有相同的分区键)一样高效吗?
在上述 3 种情况下评估性能预期的任何指导都会非常有帮助。
谢谢!
最佳答案
正如您所指出的,查询SELECT * FROM table
不是单个分区中的查询,而是全表扫描。全表扫描是“昂贵的”,因为它需要读取表中的所有数据(如果您运行它完成),但它并不像您想象的那样低效:
Scylla 或 Cassandra 不会通过查找现有分区键列表来开始此类查询 - 然后单独查询每个分区键。相反,Scylla 和 Cassandra 对分区键具有确定性顺序,即所谓的“ token ”顺序(您可以将分区键的“ token ”视为哈希函数)。各个服务器节点保存这些 token 的连续范围,因此扫描整个表是通过扫描这些连续 token 范围(也称为“vnode”)中的每一个来实现的 - 每个节点都通过单个节点有效地从其自己的节点顺序读取数据来有效实现磁盘。因此,您可以拥有一百万甚至十亿个分区,并且用于读取整个表的 SELECT * FROM table 仍将涉及从磁盘进行的大部分顺序读取 - 而不是对各个分区进行一百万或十亿次查找。
我觉得有必要提出的另一条评论是,如果您考虑只有 3 个分区,并担心将数量增加到 100,那么您就误解了 Scylla(和 Cassandra)中的数据建模。事实上,100 个分区还是太少了。您应该有超过 100 个分区。越多越好。原因是,如果只有几个巨大的分区,数据将不会均匀地分布在节点和分片(CPU)之间。如果您只有 3 个分区和 100 个 CPU,由于每个分区都由一个 CPU(在 Cassandra 中为一台服务器)拥有,因此 100 个 CPU 中只有 3 个在工作,这当然不是一个好主意。拥有一百万个分区比只有 3 个分区要好得多。
关于database - ScyllaDB 中的分区键和数据建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71813025/