Cassandra前缀搜索:能否单查询获取所有Google站点(含子域名)?
嘿,这个问题问到点子上了——毕竟Cassandra的查询能力完全由数据模型决定,和传统关系库的思路不太一样。先给你直接说结论:用你现在的表结构,没法高效地用单条查询拿到所有Google相关站点(含子域名),强行用过滤的话性能会崩;但只要调整下数据模型,就能轻松实现这个需求。
先说说现有表的问题
你的表是这么定义的:
CREATE TABLE site(url text PRIMARY KEY, count int);
这里url是唯一的分区键,Cassandra对分区键的查询逻辑以精确匹配为主,范围查询仅针对集群键(你这表没有集群键)。如果硬要写个查询比如:
SELECT * FROM site WHERE url LIKE 'com.google%' ALLOW FILTERING;
语法上虽然能跑,但这会触发全表扫描——Cassandra会遍历所有节点的所有数据来过滤出符合条件的记录,数据量稍微大一点就会超时,属于绝对要避免的反模式。
正确姿势:按查询需求重构表
Cassandra是「写时建模」,意思是你要根据读需求来设计表结构。既然你需要经常查询某个主域名下的所有子域名,那我们把主域名单独拎出来当分区键:
重构后的表结构
CREATE TABLE site_by_root_domain( root_domain text, full_url text, count int, PRIMARY KEY (root_domain, full_url) );
这里root_domain是分区键,full_url是集群键(用来在同一个分区内排序)。
插入数据
插入的时候把主域名提取出来:
INSERT INTO site_by_root_domain(root_domain, full_url, count) VALUES ('com.google', 'com.google', 5); INSERT INTO site_by_root_domain(root_domain, full_url, count) VALUES ('com.google', 'com.google.subdomain', 10);
高效查询
现在要获取所有Google相关站点,只需要一条简单的查询:
SELECT full_url, count FROM site_by_root_domain WHERE root_domain = 'com.google';
这条查询会直接定位到root_domain='com.google'对应的分区,一次性拉取所有该分区下的数据,性能拉满,完全符合Cassandra的设计思路。
额外小技巧(如果是域名场景)
如果你的url都是标准域名格式,还可以考虑把域名反转(比如com.google.subdomain变成subdomain.google.com),这样如果有更细粒度的前缀查询需求,反转后的域名可以用范围查询,但这个场景下上面的方案已经足够好用了。
总之,Cassandra不支持在现有表结构下做高效的前缀匹配查询,但通过调整数据模型,完全可以实现你要的单条查询获取所有相关站点的需求。
内容的提问来源于stack exchange,提问作者inmate

