我有 2 个关于 AWS Keyspaces 的问题。
我有一个重要的表“帖子”,其结构如下:
CREATE TABLE IF NOT EXISTS social_platform.posts (
id UUID,
user_id UUID,
title TEXT,
content TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
content_media_url TEXT,
user_username TEXT,
user_first_name TEXT,
user_last_name TEXT,
user_profile_picture TEXT,
user_role TEXT,
PRIMARY KEY (id)
);
因为 AWS Keyspaces 目前不支持物化视图或索引,所以我想出了这样的解决方案:
CREATE TABLE IF NOT EXISTS social_platform.posts_user_id_lookup (
id UUID,
user_id UUID,
PRIMARY KEY ((user_id), id)
) WITH CLUSTERING ORDER BY (id ASC);
现在我还可以搜索用户特定的帖子。
这在性能方面是否有意义,或者是否有更好的解决方案来允许查询多个键?
显然帖子应该按created_at排序。目前我有另一个查找表:
CREATE TABLE IF NOT EXISTS social_platform.posts_created_at_lookup (
date_partition DATE,
id UUID,
created_at TIMESTAMP,
PRIMARY KEY ((date_partition), created_at, id)
) WITH CLUSTERING ORDER BY (created_at DESC, id ASC);
但是有了这个结构,我需要像这样获取它:
const pageSize = parseInt(req.query.limit as string) || 10;
const lastTimestamp = req.query.lastTimestamp ? new Date(req.query.lastTimestamp as string) : new Date();
const datePartition = lastTimestamp.toISOString().split('T')[0]; // YYYY-MM-DD
console.log('Date partition:', lastTimestamp);
let query = 'SELECT id FROM posts_created_at_lookup';
let params = [];
if (lastTimestamp) {
query += ' WHERE date_partition = ? AND created_at <= ? ORDER BY created_at DESC, id ASC LIMIT ?';
params = [datePartition, lastTimestamp, pageSize];
} else {
query += ' WHERE date_partition = ? ORDER BY created_at DESC, id ASC LIMIT ?';
params = [datePartition, pageSize];
}
const timeResult = await client.execute(query, params, { prepare: true });
const orderedIds = timeResult.rows.map(row => row.id);
if (orderedIds.length === 0) {
return res.status(200).json([]);
}
const postsResult = await client.execute(
'SELECT * FROM posts WHERE id IN ?',
[orderedIds],
{ prepare: true }
);
const orderedPosts = orderedIds.map(id =>
postsResult.rows.find(post => post.id.equals(id))
);
const lastPost = orderedPosts[orderedPosts.length - 1];
const nextTimestamp = lastPost?.created_at || null;
console.log('Next timestamp:', nextTimestamp);
对我来说这似乎不是很聪明和快速。 但因为这是一种常见的做法,所以必须已经设计良好的逻辑,对吧?
从 Apache Cassandra 的角度来看,物化视图的更新是异步的,因此基表中写入的数据可能无法立即从视图中获得。
此外,使用 MV 也有一些注意事项,包括视图可能与基表不同步的风险,因此此功能始终被归类为实验性功能。我已经在 我们应该重新考虑在 Cassandra 中使用物化视图吗?.
中更详细地解释了这些内容。相对于 Cassandra 的本机二级索引,如果您担心性能,特别是当您拥有大型数据集(大量帖子、大量用户)时,它可能并不理想。
您设计另一个表来检索用户的帖子的想法是正确的。您的数据模型很接近,但设计可以简单得多。
获取按用户 ID 分区的帖子表,按时间倒序排序:
CREATE TABLE posts_by_userid (
userid uuid,
created timestamp,
postid uuid,
title text,
content text,
...
PRIMARY KEY (userid, created)
) WITH CLUSTERING ORDER BY (created DESC)
要检索特定用户的帖子,请运行:
SELECT postid, title, content FROM posts_by_userid
WHERE userid = ?
此查询将首先返回最新的帖子,然后您可以翻阅结果以检索较旧的条目。
当然,每当用户创建新帖子时,您的应用程序都必须更新多个表,但这只是批处理
INSERT
的简单问题。有关详细信息,请参阅我的另一篇文章“如何使非规范化表中的数据保持同步”。干杯!