在设计 Nebula Graph 的数据模型时,合理划分点(Vertex)和边(Edge)的属性是关键。这直接影响查询效率、数据冗余度和模型可维护性。以下是一些基本原则和实用技巧:
一、基本概念回顾
- 点(Vertex):表示实体(如用户、商品、文章),由 VID(Vertex ID) 唯一标识,包含一组 标签(Tag),每个标签可定义多个属性。
- 边(Edge):表示实体间的关系(如关注、购买、评论),由 起点、终点、边类型(Edge Type) 和 Rank(可选) 唯一标识,也可包含属性。
二、设计原则与技巧
1. 关系 vs 属性:核心判断标准
- 属于实体自身的特性 → 点属性
- 例如:用户的姓名、年龄、注册时间;商品的价格、品牌、类别。
- 属于实体间关系的特性 → 边属性
- 例如:用户关注的时间、购买的数量 / 金额、评论的内容 / 时间。
示例:社交网络模型
-- 点(用户)
CREATE TAG user (name string, -- 姓名(点属性)age int, -- 年龄(点属性)gender string -- 性别(点属性)
);-- 边(关注关系)
CREATE EDGE follow (create_time timestamp, -- 关注时间(边属性)degree int -- 关注程度(边属性)
);
2. 高基数 vs 低基数属性
- 高基数属性(变化频繁)→ 边属性
- 例如:用户每次登录的 IP、时间;订单的支付状态。
- 低基数属性(相对固定)→ 点属性
- 例如:用户的出生日期、邮箱;商品的类别。
理由:边属性可随关系变化单独更新,避免频繁修改点数据。
3. 频繁查询的属性优先建模
- 查询时常用作过滤条件的属性 → 适当冗余存储
- 例如:查询 “用户最近购买的电子产品”,可将商品类别(本属点属性)冗余到购买边中。
示例:电商模型
-- 商品点
CREATE TAG product (name string,category string, -- 类别(点属性)price double
);-- 购买边(冗余存储类别)
CREATE EDGE purchase (buy_time timestamp,quantity int,product_category string -- 冗余商品类别(边属性)
);
4. 多对多关系的中间实体 → 拆分为边
- 传统关系型数据库中的关联表 → Nebula 中的边
- 例如:用户 - 角色(多对多)在 Nebula 中建模为用户点与角色点之间的边。
示例:用户 - 角色关系
-- 用户点
CREATE TAG user (name string);-- 角色点
CREATE TAG role (role_name string);-- 关联边
CREATE EDGE has_role (assign_time timestamp, -- 分配时间(边属性)permissions string -- 权限详情(边属性)
);
5. 聚合数据 → 点属性或预计算边属性
- 需要频繁统计的数据 → 预计算并存储
- 例如:用户的粉丝数、商品的销量。
示例:用户点增加统计属性
ALTER TAG user ADD (follower_count int, -- 粉丝数(预计算的点属性)post_count int -- 发布内容数(预计算的点属性)
);
6. 时间序列数据 → 利用边的 Rank 或属性
- 按时间排序的关系 → 使用 Rank 或时间戳属性
- 例如:用户的登录历史、消息对话顺序。
示例:登录历史(使用 Rank 存储时间戳)
CREATE EDGE login_history (ip string,device string
);-- 插入时用时间戳作为 Rank,确保按时间排序
INSERT EDGE login_history(ip, device) VALUES "user1"->"user1":1630473600 ("192.168.1.1", "PC");
INSERT EDGE login_history(ip, device) VALUES "user1"->"user1":1630477200 ("10.0.0.1", "Mobile");
7. 避免过度范式化
- 图数据库适合适度冗余:为提高查询效率,可在边中存储部分点的关键属性(如商品边存储商品名称)。
- 但需权衡:冗余会增加写入成本,需根据读写比例决定。
三、常见场景建模参考
1. 社交网络
- 点:用户(ID、姓名、年龄)
- 边:关注(关注时间、亲密度)、好友(创建时间、共同好友数)
2. 电商系统
- 点:用户(ID、姓名、注册时间)、商品(ID、名称、价格)
- 边:浏览(时间、停留时长)、购买(时间、数量、金额)
3. 知识图谱
- 点:实体(名称、类型、描述)
- 边:关系(类型、权重、置信度)
四、验证与优化技巧
-
使用
PROFILE
命令分析查询性能:PROFILE GO FROM "user1" OVER follow YIELD follow._dst;
检查是否走了索引,是否有全图扫描。 -
为高频查询字段创建索引:
CREATE TAG INDEX idx_user_age ON user(age); CREATE EDGE INDEX idx_follow_time ON follow(create_time);
-
定期重构数据模型:根据实际查询模式调整点边属性划分。
五、常见误区
- ❌ 过度依赖点属性:将所有数据都放在点中,导致查询时需要频繁遍历边。
- ❌ 忽略边属性:关系特性全部缺失,无法表达复杂业务逻辑。
- ❌ 滥用多标签:一个实体用过多标签,增加查询复杂度。
合理的点边属性设计是图数据库发挥性能优势的关键。建议先从业务场景的核心查询需求出发,逐步迭代优化模型。