关系型数据库技术成熟、使用广泛,支持工具丰富而功能强大,数据存储、查询效率高,因此在语义数据存储尚未成熟、无有效工具出现时,很自然地被广泛应用于本体数据的存储。由于本体模型和关系模型的差异,基于关系型数据库的本体存储存在多种模式(李曼等, 2005):
(1) 水平模式
该模式在数据库中只用一张表来表示本体,表中列为本体的属性,表中的一个记录对应本体中的每个实例。由于在本体的更新、进化过程中,本体属性数量和名称都可能发生变化,且并非所有实例都具有相同属性。因此,此模式数据表列需要经常变化,且存在大量空值,只适用于小规模的静态的本体。
(2) 垂直模式
这种模式只包含一张三元组表,表中每个记录对应一个三元组,用三元组的形式来描述本体全部信息。此模式结构稳定,但是可读性差,难以构造SQL以进行查询,不利于本体应用。
(3) 分解模式
基本思想是将数据库进行模式分解。现有的分解模式的方法中,第一种是基于类的分解模式,即以类名为表名,类的属性为表的列,为本体中的每个类都创建一张单独的表;另外一种是基于属性的分解模式,即以属性名为表名,表中包含两列,分别代表RDF 中的Subject 和Object,为本体中的每个属性创建一张单独的表。此模式需随着本体的更新、修改不断新建、删除数据表,效率低,代价大,也不利于本体的应用。
(4) 其他模式
包括将上述几种模式混合使用的混合模式和将OWL 描述词汇映射为数据表以存储存在此关系的本体资源、提高查询效率的模式等。
语义网开发框架Jena 的SQL 数据库引擎SDB 采用一种混合模式,将本体内容存储到4 个相互关联的数据表中:节点表nodes、前缀表prefixes、四元组表quads 和三元组表triples。SDB 将本体视为图(Graph)的集合,RDF 中的Subject、Predicate 和Object 都是图中的结点,一个数据集可以有多个图。因此,顾名思义,nodes 存储本体中的结点,其列记录结点数据类型、语言等基本的属性;prefiexes 存储本体中定义的前缀;quads 存储命名图(Named Graph)和对应的RDF 记录;triples 存储RDF 三元组,其值为nodes 表中的主键值,实例属性和关系全部采用s-p-o(subject、predicate 和object)形式表达。SDB 模式表结构稳定、以一定的存储空间代价换取较高的数据增删改查效率,是一种较为优秀的本体关系数据库存储模式。
SDB 中存在“layout2/hash”和“layout2/index”两种主要的表模式,其区别是:“layout2/index”模式中的nodes 表以“id”列为主键,以“hash”列为索引;而“layout2/hash”没有“id”列,以“hash”列为主键。SDB 数据库连接信息、布局模式等内容可以在SDB 的配置文件(如下)中进行指定。
# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0 # 前缀定义 @prefix sdb: <http://jena.hpl.hp.com/2007/sdb#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> . <#store> rdf:type sdb:Store ; sdb:layout "layout2" ; # "layout2", "layout2/hash" or "layout2/index" sdb:connection <#conn> ; . <#conn> rdf:type sdb:SDBConnection ; sdb:sdbType "postgresql" ; # "oracle", "postgresql", "mysql" sdb:sdbHost "localhost";#"localhost:1521";# 地址,可加端口 :port sdb:sdbName "sdb_test"; sdb:sdbUser "user"; sdb:sdbPassword "pw"; sdb:driver "org.postgresql.Driver" ;#"oracle.jdbc.driver.OracleDriver";# 数据库驱动
采用配置文件设置数据库连接信息之后,采用如下方法读取本体文件并存储到数据库相应数据表中。
String file = "src/main/resources/CCS.owl";//本体文件地址 // 连接数据库,使用配置文件 Store store = SDBFactory.connectStore("src/main/resources/sdb-pgsql.ttl"); // 创建数据库表 store.getTableFormatter().create(); Model model = SDBFactory.connectDefaultModel(store); // 读取owl文件到model中 try{ FileManager.get().readModel(model, file, "OWL"); } catch (Exception e){ throw new IllegalArgumentException("文件不存在!"); } // System.out.println(model.size()); // 关闭连接和储存,释放资源 store.getConnection().close(); store.close();
SDB 中的三元组表只记录结点的hash 或id 值,可读性差,难以直接构造SQL语句进行查询。但实际上SDB 设计目也不在于基于传统SQL 语句的本体查询,而是作为Jena 框架的关系数据库引擎,实现本体持久化存储。本体数据的查询则借助于Jena 的查询组件,使用本体查询语言SPARQL 实现。SDB 中利用SPARQL 语句实现本体查询的具体算法如下所示:
String queryString = "Select * {?s ?p ?o}"; Store store = SDBFactory.connectStore(ttl); //连接数据库,使用配置文件 Query query = QueryFactory.create(queryString); // 创建查询 Dataset dataset = DatasetStore.create(store); QueryExecution qe = QueryExecutionFactory.create(query, dataset); ResultSet resultSet = qe.execSelect(); ResultSetFormatter.out(resultSet); //控制台格式化输出查询结果 qe.close(); //关闭查询 store.getConnection().close(); //关闭连接 store.close();
——摘自《地学数据时间本体及其在语义检索中的应用——以地质年代本体为例》