Cassandra 卡桑德拉-按电话号码查询
为这个冗长的问题提前道歉。。。 我使用Cassandra数据库来存储用户之间的消息。 每个用户都有一个专用的电话号码,我需要(a)查询两个号码之间的对话,而不管是谁发送/接收的(b)查询与特定号码相关的所有消息,而不管它是发送还是接收的。这两个查询都需要按时间戳按降序分页 考虑以下简化的模式Cassandra 卡桑德拉-按电话号码查询,cassandra,Cassandra,为这个冗长的问题提前道歉。。。 我使用Cassandra数据库来存储用户之间的消息。 每个用户都有一个专用的电话号码,我需要(a)查询两个号码之间的对话,而不管是谁发送/接收的(b)查询与特定号码相关的所有消息,而不管它是发送还是接收的。这两个查询都需要按时间戳按降序分页 考虑以下简化的模式 create table messages ( app_id uuid, message_id text, from_number text, to_number text,
create table messages
(
app_id uuid,
message_id text,
from_number text,
to_number text,
timestamp bigint,
body text,
primary key (app_id, timestamp, message_id)
) WITH CLUSTERING ORDER BY (timestamp DESC);
以及以下数据
+------------------------------------+-------------+------------------------------------+-----------+----------+
|app_id |timestamp |message_id |from_number|to_number |
+------------------------------------+-------------+------------------------------------+-----------+----------+
|aae22284-04ee-11eb-9391-bb67d1e2f833|1599376014000|ae8b041e-04ee-11eb-9391-bb67d1e2f833|1111111111 |2222222222|
|aae22284-04ee-11eb-9391-bb67d1e2f833|1599376014001|c7e81302-04ee-11eb-9391-bb67d1e2f833|2222222222 |1111111111 |
+------------------------------------+-------------+------------------------------------+-----------+----------+
为了按数字进行查询(两个同时进行,每个单独进行),我正在考虑在此模式中标识为number\u list
、number\u list\u freezed
和numbers\u concat
的多个选项
create table messages
(
app_id uuid,
message_id uuid,
from_number text,
to_number text,
timestamp bigint,
number_list list<text>, <--- option 1
number_list_frozen frozen<list<text>>, <--- option 2
numbers_concat text, <--- option 3
primary key (app_id, timestamp, message_id)
)
WITH CLUSTERING ORDER BY (timestamp DESC);
CREATE INDEX idx_numbers_list ON messages (number_list);
CREATE INDEX idx_numbers_list_frozen ON messages (FULL(number_list_frozen));
CREATE INDEX idx_numbers_concat ON messages (numbers_concat);
选项1-列表
将使用编号列表,并允许进行以下查询
SELECT from_number, to_number, timestamp
FROM messages
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list contains '1111111111'; // or 2222222222
当您想按任意数字进行查询时,这种方法很有效,但不能同时按任意数字进行查询,也就是说,这种方法不起作用
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list = ['1111111111', '222222222222'];
(获取错误<代码>“集合列'编号'列表'(列表)不能受'='关系的限制”)
在尝试以下操作时也是如此-
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list contains '1111111111' AND number_list contains '222222222222';
SELECT from_number, to_number, timestamp
FROM messages
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND numbers_concat = '1111111111-2222222222';
我收到此错误“无法执行此查询,因为它可能涉及数据筛选,因此可能具有不可预测的性能。如果您希望在性能不可预测的情况下执行此查询,请使用“允许筛选”。
添加ALLOW FILTERING确实可以解决这个问题,但不能确定它对性能的影响
选项2-冻结列表
为了解决获取两者的问题,我尝试使用一个带有完整索引的冻结列表,它似乎只适用于名称所暗示的完全匹配,因此查询两个数字是可行的,但查询单个数字却不行(因为Cassandra将数据序列化为单个值)
e、 g.这很有效-
SELECT from_number, to_number
FROM sms_server.messages10
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list_frozen = ['1111111111', '222222222222'];
但事实并非如此(除非我添加了允许过滤)
- 冻结列表在插入数据库之前将在应用程序级别进行排序,以确保一致性(无论通信方向如何,两个数字的冻结列表始终相同)。 我还尝试使用一个元组,在查询时它似乎类似于冻结列表
上方的行中,无论消息的方向如何,concat
始终等于1111111111-2222222
我可以运行以下命令-
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list contains '1111111111' AND number_list contains '222222222222';
SELECT from_number, to_number, timestamp
FROM messages
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND numbers_concat = '1111111111-2222222222';
但这只是冻结列表的一种替代方法,因此唯一的问题是字符串索引与冻结列表索引相比是否有任何性能提升
选项4-同时使用列表和冻结列表,每个查询一个
选项5-使用地图
在这个选项中,我同时删除了from_number和to_number,并使用了一个映射
创建表消息
(
应用程序id uuid,
消息_iduuid,
时间戳bigint,
数字地图
主键(应用程序id、时间戳、消息id)
)
使用聚类顺序(时间戳DESC)
e、 g.{'from':'2222222','to':'111111111'}
它允许运行以下命令
select * from messages
where app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
and numbers_map contains '111111111111';
但再次检查两者,我必须使用允许过滤
SELECT from_number, to_number
FROM sms_server.messages10
WHERE app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
AND number_list_frozen contains '1111111111';
select * from messages
where app_id = aae22284-04ee-11eb-9391-bb67d1e2f833
and numbers_map contains '111111111111' and numbers_map contains '222222222222' ALLOW FILTERING;
最后是我的问题
=
和包含,进行查询,而不使用允许筛选
- 注意-我知道使用物化视图可能会获得相同的结果,但我正计划转向AWS托管的Cassandra解决方案(Keyspaces),该解决方案不支持MVs