我在 Apache Cassandra 数据库中有一个包含用户通道的表。查询负责获取通道列表并获取有关通道的数据。其中一个查询需要ALLOW FILTERING,我们认为最好的选择是复制表,只有它有一个主键((channel_id,bucket),user_id),然后问题就出现了,是否有类似的东西Apache Cassandra 中的链接,以便数据库不必不断写入和更新两个表中的数据。如果您知道不需要这样做的解决方案,那么我将非常感谢该解决方案
create table channels
(
user_id bigint,
bucket int,
channel_id bigint,
flags int,
permissions bigint,
type int,
primary key ((user_id, bucket), channel_id)
)
SELECT * FROM channels WHERE user_id = :user_id AND bucket = :bucket
SELECT * FROM channels WHERE channel_id = :channel_id ALLOW FILTERING
建议创建两个表并在应用程序级别进行管理。这就是所谓的非规范化;让我解释一下。
关于允许过滤:
SELECT * FROM channels WHERE channel_id = :channel_id ALLOW FILTERING
此查询会扫描整个数据集,因为
channel_id
不是分区键的一部分。 ALLOW FILTERING
是 Cassandra 反模式。它会导致集群范围内的读取、超时和高资源消耗等低效率问题。
关于复制表格的建议:
复制表是正确的方法,但您似乎正在寻找“链接”(如外键)来自动同步两个表。 Cassandra 不支持这一点,因为它不是关系数据库并且支持非规范化。
关于Cassandra本身:
Cassandra 专为快速写入和水平扩展(写入优化)而设计。对于不同的查询模式,鼓励跨表复制数据,因为写入成本较低,但读取成本可能很高。 想象一下您的集群中有数百个节点。您希望查询在写入和读取数据时仅涉及最少量的节点,以便您可以在需要时轻松水平扩展。 Cassandra 的架构应该针对您的查询进行设计。如果您有两个查询(
user_id
和 channel_id
),您将需要两个具有适当主键的表来优化这两个查询。
建议的解决方案:
创建两个表:
CREATE TABLE channels_by_user (
user_id bigint,
bucket int,
channel_id bigint,
flags int,
permissions bigint,
type int,
PRIMARY KEY ((user_id, bucket), channel_id)
);
和
CREATE TABLE channels_by_channel_id (
channel_id bigint,
bucket int,
user_id bigint,
flags int,
permissions bigint,
type int,
PRIMARY KEY (channel_id, bucket)
);
在应用程序级别同时写入两个表。由于 Cassandra 中的写入速度很快,因此这种重复不会显着影响性能。