Operational Property Graphs,中文通常译为“操作属性图”。

作为23ai中被官方highlight出的新特性之一,我们先看下官方的原文描述:

  • Operational Property Graphs in SQL

Developers can now build real-time graph analysis applications against operational

data directly in the Oracle Database, utilizing its industry leading security, high

availability and performance capabilities.

简单说,开发者可以直接在Oracle 23ai中进行实时图分析,而不需要额外的图数据库。

为了不纯扯概念,更好的直观体验,下面我们直接按照官方文档给出的一个简单示例来动手练习体验下:

本次测试环境: Oracle Database 23ai(23.4.0.24.05)

本次用到技术: 原生JSON数据类型、操作属性图。

本次测试意义: 直观体验Oracle数据库多模、融合的设计理念所带来的便利性。

  • 1.准备测试表和测试数据
  • 2.创建属性图
  • 3.体验SQL查询属性图

1.准备测试表和测试数据

这里创建的示例,整体构成了一个基本的数据库结构,测试表 university、persons、students、friendships 分别用于存储大学、人员、学生和朋友关系的数据。

特别需要注意的是,persons 表中的 person_data 字段是 JSON 类型,用于存储原生 JSON 数据。这也是23ai在其多模能力上的一种体现,使其能够更适合用来构建现代的应用平台。

-- 1.CREATE TABLE university
CREATE TABLE university (
id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
name VARCHAR2(10),
CONSTRAINT u_pk PRIMARY KEY (id)); INSERT INTO university (name) VALUES ('ABC');
INSERT INTO university (name) VALUES ('XYZ');
commit; -- 2.CREATE TABLE persons
-- 包含存放原生的JSON数据类型字段person_data,这里是存放了这个人的部门信息和岗位角色
CREATE TABLE persons (
person_id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT
BY 1),
name VARCHAR2(10),
birthdate DATE,
height FLOAT DEFAULT ON NULL 0,
person_data JSON,
CONSTRAINT person_pk PRIMARY KEY (person_id)
); INSERT INTO persons (name, height, birthdate, person_data)
VALUES ('John', 1.80, to_date('13/06/1963', 'DD/MM/YYYY'), '{"department":"IT","role":"Software Developer"}');
INSERT INTO persons (name, height, birthdate, person_data)
VALUES ('Mary', 1.65, to_date('25/09/1982', 'DD/MM/YYYY'), '{"department":"HR","role":"HR Manager"}');
INSERT INTO persons (name, height, birthdate, person_data)
VALUES ('Bob', 1.75, to_date('11/03/1966', 'DD/MM/YYYY'), '{"department":"IT","role":"Technical Consultant"}');
INSERT INTO persons (name, height, birthdate, person_data)
VALUES ('Alice', 1.70, to_date('01/02/1987', 'DD/MM/YYYY'), '{"department":"HR","role":"HR Assistant"}');
commit; -- 3.CREATE TABLE students
-- 这里官方文档有个错误,属于低级错误,插入字段数量和具体赋值对应不上,此处已修正
CREATE TABLE students (
s_id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
s_univ_id NUMBER,
s_person_id NUMBER,
subject VARCHAR2(10),
CONSTRAINT stud_pk PRIMARY KEY (s_id),
CONSTRAINT stud_fk_person FOREIGN KEY (s_person_id) REFERENCES persons(person_id),
CONSTRAINT stud_fk_univ FOREIGN KEY (s_univ_id) REFERENCES university(id)
); INSERT INTO students(s_univ_id, s_person_id, subject) VALUES (1,1,'Arts');
INSERT INTO students(s_univ_id, s_person_id, subject) VALUES (1,3,'Music');
INSERT INTO students(s_univ_id, s_person_id, subject) VALUES (2,2,'Math');
INSERT INTO students(s_univ_id, s_person_id, subject) VALUES (2,4,'Science');
commit; -- 4.CREATE TABLE friendships
-- 这里 meeting_date 可理解为朋友之间相遇的日期
CREATE TABLE friendships (
friendship_id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
person_a NUMBER,
person_b NUMBER,
meeting_date DATE,
CONSTRAINT fk_person_a_id FOREIGN KEY (person_a) REFERENCES persons(person_id),
CONSTRAINT fk_person_b_id FOREIGN KEY (person_b) REFERENCES persons(person_id),
CONSTRAINT fs_pk PRIMARY KEY (friendship_id)
); INSERT INTO friendships (person_a, person_b, meeting_date) VALUES (1, 3, to_date('01/09/2000', 'DD/MM/YYYY'));
INSERT INTO friendships (person_a, person_b, meeting_date) VALUES (2, 4, to_date('19/09/2000', 'DD/MM/YYYY'));
INSERT INTO friendships (person_a, person_b, meeting_date) VALUES (2, 1, to_date('19/09/2000', 'DD/MM/YYYY'));
INSERT INTO friendships (person_a, person_b, meeting_date) VALUES (3, 2, to_date('10/07/2001', 'DD/MM/YYYY'));
commit;

2.创建属性图

-- 5.CREATE PROPERTY GRAPH students_graph
-- 这里是关键的属性图创建:
CREATE PROPERTY GRAPH students_graph
VERTEX TABLES (
persons KEY (person_id)
LABEL person
PROPERTIES (person_id, name, birthdate AS dob)
LABEL person_ht
PROPERTIES (height),
university KEY (id)
)
EDGE TABLES (
friendships AS friends
KEY (friendship_id)
SOURCE KEY (person_a) REFERENCES persons(person_id)
DESTINATION KEY (person_b) REFERENCES persons(person_id)
PROPERTIES (friendship_id, meeting_date),
students AS student_of
SOURCE KEY (s_person_id) REFERENCES persons(person_id)
DESTINATION KEY (s_univ_id) REFERENCES university(id)
PROPERTIES (subject)
);

这个对于DBA出身的小伙伴们来说,可能会很陌生,也稍难理解些。所以这里详细解释说明下:

上面的SQL语句是在Oracle数据库中,直接创建了一个属性图students_graph,具体包含两个顶点表(persons和university)和两个边表(friendships和students)。

那什么是顶点表?边表又是啥?

在图数据库中,顶点(Vertex)和边(Edge)是构建图数据模型的基本元素:

顶点表(Vertex Table):表示图中的实体或对象。

边表(Edge Table):表示图中的关系或连接,定义了两个顶点之间的关系。

具体在我们这个例子中,顶点表personsuniversity表示人员和大学。

边表friendshipsstudents表示人员之间的友谊关系和人员与大学之间的学生关系。

了解了基本概念后,再回过头来看这个SQL定义的属性图,拆解分析后是不是很清晰了呢?

  • VERTEX TABLES(顶点表)
-- persons 表:
KEY (person_id):指定主键。
LABEL person:给顶点赋予person标签。
PROPERTIES (person_id, name, birthdate AS dob):指定属性,其中birthdate属性重命名为dob。
LABEL person_ht:给顶点赋予person_ht标签。
PROPERTIES (height):指定属性height。 -- university 表:
KEY (id):指定主键。
  • EDGE TABLES(边表)
-- friendships 表(别名friends):
KEY (friendship_id):指定主键。
SOURCE KEY (person_a) REFERENCES persons(person_id):源顶点引用persons表的person_id。
DESTINATION KEY (person_b) REFERENCES persons(person_id):目标顶点引用persons表的person_id。
PROPERTIES (friendship_id, meeting_date):指定属性。 -- students 表(别名student_of):
SOURCE KEY (s_person_id) REFERENCES persons(person_id):源顶点引用persons表的person_id。
DESTINATION KEY (s_univ_id) REFERENCES university(id):目标顶点引用university表的id。
PROPERTIES (subject):指定属性。

3.体验SQL查询属性图

实际使用了Oracle的图表查询语言来查找名为“John”的人的朋友,并返回这些朋友的名字。

SELECT *
FROM GRAPH_TABLE ( students_graph
MATCH (a IS person) -[e IS friends]- (b IS person)
WHERE a.name = 'John'
COLUMNS (b.name)
);

这个SQL同样会让DBA觉得不适应,看起来怪怪的,但对开发人员应该很容易理解了。为了让DBA出身的小伙伴们也能理解,我们继续逐一来解释:

-- FROM GRAPH_TABLE:
使用 GRAPH_TABLE 函数来查询图数据。 -- students_graph:
这是之前创建的属性图的名称。 -- MATCH (a IS person) -[e IS friends]- (b IS person):
MATCH:定义图的模式。
(a IS person):匹配标签为 person 的顶点 a。
-[e IS friends]-:匹配标签为 friends 的边 e,连接顶点 a 和 b。
(b IS person):匹配标签为 person 的顶点 b。 -- WHERE a.name = 'John':
过滤条件:顶点 a 的 name 属性为 'John'。 -- COLUMNS (b.name):
定义返回的列:返回顶点 b 的 name 属性。

当然,除了返回朋友的名字,还可以返回更多信息,比如和这位朋友友谊开始的日期:

SELECT *
FROM GRAPH_TABLE ( students_graph
MATCH (a IS person) -[e IS friends]- (b IS person)
WHERE a.name = 'John'
COLUMNS (b.name, e.meeting_date)
);

只是在COLUMNS条件中,增加了e.meeting_date,是不是咋一看很晦涩难懂,实际理解了,其实跟普通SQL一样的简单清晰呢?

上面示例的两个SQL的查询结果如下:

23:02:23 PRIMARY @ORCL -> JINGYU @PDB1> SELECT *
FROM GRAPH_TABLE ( students_graph
MATCH (a IS person) -[e IS friends]- (b IS person)
WHERE a.name = 'John'
COLUMNS (b.name)
);23:02:23 2 23:02:23 3 23:02:23 4 23:02:23 5 23:02:23 6 NAME
----------
Mary
Bob Elapsed: 00:00:00.00
23:02:24 PRIMARY @ORCL -> JINGYU @PDB1> SELECT *
FROM GRAPH_TABLE ( students_graph
MATCH (a IS person) -[e IS friends]- (b IS person)
WHERE a.name = 'John'
COLUMNS (b.name, e.meeting_date)
);23:02:35 2 23:02:35 3 23:02:35 4 23:02:35 5 23:02:35 6 NAME MEETING_D
---------- ---------
Mary 19-SEP-00
Bob 01-SEP-00 Elapsed: 00:00:00.01
23:02:35 PRIMARY @ORCL -> JINGYU @PDB1>

清理实验环境:

删除本次测试的表和属性图,方便快速清理环境或重新测试:

-- 先删除有外键约束的表:
drop table students purge;
drop table friendships purge; -- 再删除其他表:
drop table university purge;
drop table persons purge; -- 删除属性图:
drop PROPERTY GRAPH students_graph;

参考的官方文档链接:

注:官方文档给出的例子有些小问题,已在文章中代码部分修正,方便大家直接复制粘贴文中代码来进行快速测试验证。

最后总结一下本文都涵盖了哪些内容:

  • 例子中提到的原生JSON数据类型,其实还比较容易理解,无非就是把JSON数据存储到对应这个数据类型的字段中。注意这里并没有提到JSON关系二元性,这个话题以后空了再单独研究讨论。

  • 有个细节,创建表语句中使用的自增id,GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),这其实不算是一个很新的功能,但如果读者对Oracle的认知还停留在11g时代,可能还会认为Oracle不支持类似像MySQL这种自增ID的设计,需要序列配合实现。而实际上,早在12c之后就已经支持了这种方式。

  • 介绍并演示操作属性图这个特性。

回到本文实验的主题,操作属性图(Operational Property Graphs)其实对传统偏管理方向的DBA来说,理解上还是有一些技术挑战的。

比如开始很可能照例子创建成功了,也不知道如何用,创建出来的属性图想直接查询看到底是个啥内容,发现自己还不会正确的使用语法。

笔者也是,但静下心来,花些时间看看文档,理解这类新特性之后,就会发现其强大之处,也容易积极推广给有需要的开发人员来使用,实现简化开发,降低使用属性图的门槛,提升工作效率。

Operational Property Graphs到底是个啥?的更多相关文章

  1. Python的特性(property)

    特性(property) 特性是对类的一个特定属性进行拦截,在操作这个属性时,执行特定的函数,对属性的操作进行拦截. 特性的实现 特性使用property类来实现,也可以使用property装饰器实现 ...

  2. Neo4j沙盒实验申请过程步骤(图文详解)

    不多说,直接上干货! 参考博客 http://blog.csdn.net/u012318074/article/details/72793632    (对此表示感谢) 前期博客 我暂时是将Neo4j ...

  3. Python第七章-面向对象高级

    面向对象高级 一. 特性 特性是指的property. property这个词的翻译一直都有问题, 很多人把它翻译为属性, 其实是不恰当和不准确的. 在这里翻译成特性是为了和属性区别开来. 属性是指的 ...

  4. 论文阅读: CCF A 2022 MVD: 基于流敏感图神经网络的内存相关漏洞检测 (ICSE)

    Motivation: 内存相关漏洞会导致性能下降和程序崩溃,严重威胁到现代软件的安全性. 静态分析方法使用一些预定义的漏洞规则或模式来搜索不正确的内存操作,然而,定义良好的漏洞规则或模式高度依赖于专 ...

  5. 探究@property申明对象属性时copy与strong的区别

    一.问题来源 一直没有搞清楚NSString.NSArray.NSDictionary--属性描述关键字copy和strong的区别,看别人的项目中属性定义有的用copy,有的用strong.自己在开 ...

  6. 在开发中到底要不要用var?

    var是.net的一个语法糖,在Resharper中推荐都使用这个关键字,平常我也是经常用:但是在跟其他程序员推广使用时,他的一些考虑引发了我的深思,到底该不该使用这个关键字呢? 我使用的理由 我使用 ...

  7. iOS多线程到底不安全在哪里?

    iOS多线程安全的概念在很多地方都会遇到,为什么不安全,不安全又该怎么去定义,其实是个值得深究的话题. 共享状态,多线程共同访问某个对象的property,在iOS编程里是很普遍的使用场景,我们就从P ...

  8. OC中的@property详解

    简介: @property 生成了变量的get set 方法,同时指定了变量名称. 例如@property (nonatomic,strong) NSString *name;表示生成了_name私有 ...

  9. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  10. Property和attribute的区别[转]

    Attribute和Property都可以翻译成“属性”,有的地方用Attribute表示“属性”,有的地方又在用Property,初 学者常常在这两个单词间“迷失”,甚至认为二者没有区别,是一样的. ...

随机推荐

  1. [FAQ] swagger-php 支持 Authorization Bearer token 校验的用法

    @OA\SecurityScheme 可以是 Controller 层面也可以是 Action 层面. 类型 type="apiKey". in="header" ...

  2. [FAQ] Python list 的值是带有小括号的是什么意思 ?

    python 中的 list 即列表,是用中括号 [ ] 表示的数组列表: dict 即字典,是用花括号 { } 表示的 json 对象: tuple 即元祖,是用小括号表示的序列: 见到它们之间的组 ...

  3. 从 Rollover+curator 到 ILM

    数据量增长,当前存在的问题: 查询与写入越来越慢,聚合的速度慢的离谱,聚合的数据量大一些的话,可能出现超时失败,甚至OOM 磁盘和内存资源以肉眼可见的速度快速消耗,甚至出现满载的情况 JVM频繁GC, ...

  4. 程序员天天 CURD,怎么才能成长,职业发展的思考(2)

    接着上一篇:程序员天天 CURD,怎么才能成长,职业发展思考 上一篇写到了用年限来谈程序员的发展,在 4 - 6 年这个时间段需要做的一些事情,接着写这个时间段的. 第 4.5 年时候,你可能会做一些 ...

  5. ORA-600 [kkqjpdpvpd: no join pred found.]

    场景 一个比较大的sql查询,报出了ORA-600 [kkqjpdpvpd: no join pred found.] 解决方法: 根据metalink提供的解决思路.当于当前session,执行如下 ...

  6. Go pprof 认知到实践

    快速开始 测试环境:go version go1.22.2 windows/amd64,源代码开源在 https://github.com/oldme-git/teach-study/tree/mas ...

  7. WEB服务与NGINX(26)- 实现Nginx高并发系统内核参数优化

    1. 实现Nginx高并发系统内核参数优化 由于默认的Linux内核参数考虑的是最通用场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更 ...

  8. NETCore中实现一个轻量无负担的极简任务调度ScheduleTask

    至于任务调度这个基础功能,重要性不言而喻,大多数业务系统都会用到,世面上有很多成熟的三方库比如Quartz,Hangfire,Coravel 这里我们不讨论三方的库如何使用 而是从0开始自己制作一个简 ...

  9. Kmesh进入CNCF云原生全景图,实现网格治理sidecarless化

    本文分享自华为云社区<Kmesh进入CNCF 云原生全景图> ,作者:云容器大未来. 近日,Kmesh 正式进入 CNCF 云原生全景图,位于 Service Mesh 类别下. CNCF ...

  10. MLP实现波士顿房屋价格回归任务

    1. 数据集 波士顿房屋价格.csv文件,文件中的数据有可能不完整,部分数据如下: CRIM, ZN ,INDUS ,CHAS,NOX,RM,AGE,DIS,RAD,TAX,PTRATIO,LSTAT ...