这篇论文提出一种改进的病例图谱存储方案,即多元关系到RDF三元组的转化方案。基于原始病例数据具有空值多、谓词数量多且为此不固定等特征,采用基于改进三元组表的存储方案,将病例RDF三元组的实体和属性进行ID化。在此基础上,设计实体类型表,面向病例图谱使用SPARQL-to-SQL查询转换算法。实验结果:与基于类型的存储方案相比,基于图谱的RDF存储方案具有较高的查询效率。
RDF:
- 资源描述框架(Resource Description Framework,RDF)为一种元数据框架,是对结构化的元数据进行编码、交换和再运用的一个基础结构。RDF的意义在于能够针对资源进行描述。它能非常方便地捕获非XML文档信息。它的目的是为描述这些资源提供一种通用的方法,方便它们的分类、建立目录、查找和获取。
- RDF方式采用伪语法方式来表达RDF资源的表达式或语句。RDF语句(statement)是由三个部分组成的:
- 被描述的资源、
- 对象被声明的方面或者特性,
- 该特性的实际值。
这三个部分各自的术语为主体(subject)、谓词(predicate)和对象(object)
论文中心:提出一种改进的病例图谱存储方案
解决的问题:提高查询效率
文章结构:
一、概述:
为发现电子病例中数据的深层含义,将电子病历中的数据以RDF格式发布,形成病例图谱,并与开放式知识库(如中文知识库)相关联,用于对疾病检测、用药推荐、相似病人发现等研究。
1、RDF存储方式:
- 原生图:Allegro Graph、Neo4j等
- 关系型数据库:mysql、Oracle等
2、现有存储方案及问题:
- 三元组表存储:
将主谓宾分别存储在关系表的三列
问题:复杂查询会造成大量的自连接而降低查询性能。
- 水平存储:
行:主体,列:数据集中所有属性(星状查询结构)
问题:表中存在大量列和空值,一个属性存在具有多个值的情况。
- 基于类型存储(改进水平存储):
相同类型主体存于一张表中,每张表以水平存储方式(解决列数多的问题)
问题:空值问题、多值性问题依然存在、大多数查询会涉及多个表连接或合并操作。
- 基于谓词存储(改进三元组存储):
将三元组表重写为N(数据集中谓词个数)张包含2列的表,该表以谓词命名,第一列:谓词对应主体,第二列:主体在该谓词上的值。(解决空值问题、多值性问题)
问题:增加查询时表连接的数量,表增多加大了维护难度
针对问题提出基于知识图谱的医疗病例数据存储方案。
二、病例知识图谱构建及关联基础知识库
1、病例知识图谱构建
原始关系数据表:
对应部分知识图谱
2、关联基础知识库
目的:进一步分析某病人患过哪些疾病、做过哪些手术、患过某一疾病的的患者拥有哪些共同点等。
与中文症状知识库进行关联:
上方:病例图谱中部分元素
下方:中文症状知识库中部分元素
三、存储方案
1、多元关系存储
如何将病例中多元关系转换成RDF三元组格式,是本文难点。
多元关系到 RDF 三元组的转化遵循的规则:多元关系 { < subject,predicate,object,a1,a2,…,an > ,n > 0} 。
- subject :三元组的主语
- object :三元组的宾语
- predicate:主语和宾语之间的关系
- a1,a2,…,an 表示该三元组的描述信息,与原三元组共同构成多元关系。
此多元关系转换成等价三元组为:
< subject,edge_predicate,edgeType_id >
< edgeType_id,detailType,object >
< edgeType_id,a1,a1 _value >
< edgeType_id,a2,a2 _value >
< edgeType_id,a3,a3 _value >
?
< edgeType_id,an,an _value >
按照规则,图 3 可以转换为:
< 张三,edge_operation,operationEdge1 >
< operationEdge1,时间,2014 年 >
< operationEdge1,operationDetail,静脉穿刺术 >
< 赵四,edge_operation,operationEdge2 >
< operationEdge2,时间,2015 年 >
< operationEdge2,operationDetail,静脉穿刺术 >
2、数据集转换
每张表中一行代表一个实体,字段名代表属性,列值代表对应的属性值,根据属性类型划分表。
- 属性属于实体(病人性别、血型、手术代码等) 一一一一> 详情表
- 属性属于对三元组的描述信息(住院时间、化验结果、化验时间等)一一一一>相应的关系表(如手术关系表)
3、表结构设计
列举了基于三元组存储方案、水平存储方案、基于谓词存储方案、基于类型存储方案来设计表结构的不足。
本文改进了三元组表存储方案来进行表结构设计。
设计4张表:
- 实体表:实体名称、entity_id(将字符串类型实体名称映射为数值类型ID,数据库对数值类型查询效率高于字符串类型,从而 提高查询效率)
- 属性定义表:谓词、attr_id
- 属性表:每条三元组的唯一id、entity_id、attr_id、attr_value
- 实体类型表:entity_id、type_id(实体类型id)
四、查询集
为全面评估各存储方案的性能,通过对问题的分析,根据查询过程中将要使用到的节点和边,将问题分成以下四种来进行查询。
- “1 个节点1 条边”
- “2 个节点 1 条边”
- “2 个节点 2 条边”
- “3 个节点2 条边”4 类
五、查询转换引擎
设计满足针对病例图谱的常用统计分析类查询需求的SPARQL-to-SQL转换算法。
- 难点1:如何将SPARQL中的多元关系查询映射到对应的三元组。
解决方法:在进行每一步查询的时候为属性表分配别名 attribute_i,并令 attribute_i. attr_value = attribute_i+ 1. entity_id
- 难点2:SPARQL 查询语句中的查询变量到SQL 查询语句中的查询变量的映射和 SPARQL 中的聚合函数到 SQL 中的聚合函数的转化
解决方法:算法 4 SPARQL-to-SQL 算法
输入 SPARQL
输出 SQL
1. prefix ← PREFIX
2. URI ← URI of prefix
3. triples ← split SPARQL. WHERE_Clause with " ."
4. for each triple in triples do
5. if triple contains " EMPI" then
6. add entity name to SQL.SELECT_CLAUSE
7. add entity to SQL.FROM_CLAUSE
8. add “attribute _ 1.entity _ id = entity.entity _ id and attribute_1.entity_id = attribute_2.entity_id”to SQL.WHERE_CLAUSE
9. predicate ← concat URI and triple.predicate
10. ID←getIDFromAttributeDefinitionTable( predicate)
11. if triplePattern is < ?s p o > then
12. add“attribute_i.attr_id = ID and attribute_i.value = o and attribute_i.entity _id = attribute_i + 1.entity _id” to SQL.WHERE_CLAUSE
13. add“attribute attribute_i”to SQL.FROM_CLAUSE
14. else if triplePattern is < ?s p ?o > then
15. if triple.?o = nextTriple.?s then
16. add“attribute_i.attr_id = ID and attribute_i.attr_value =attribute_i + 1.entity_id” to SQL.WHERE_CLAUSE
17. else if triple is followed by FILTER then
18. add“attribute_i.attr_id = ID and F( filter) ”to SQL.WHERE_CLAUSE
19. end for
20. values ← split SPARQL.SELECT_CLAUSE with " "
21. if values contain“COUNT /AVG /MIN /MAX”then
22. add “COUNT /AVG /MIN /MAX ( attribute _ ilast.value) ) ”to SQL.SELECT_CLAUSE
算法 4 中的 F( filter) 函数用于将 SPARQL 中的FILTER约束条件转换为 SQL 中 的 约 束 条 件,如FILTER( ?age > 70) 转换为 attribute_i. attr_value >70,attribute_ilast 代表最后一个属性表的别称。
根据算法 4,查询“2015 年之后入院的女性患者”的 SPARQL 语句为:
PREFIX medical: < http: / /shuguangemr/resource / attribute _definition / >
SELECT ?EMPI
WHERE{
?patient medical: EMPI ?EMPI.
?patient medical: sex“女”.
?patient medical: hospitalEdge ?edge.
?edge medical: inTime ?time.
FILTER( ?time >“2015-01-01 00: 00: 00”^^xsd: datetime)
}
转换成 SQL 为:
SELECT entity.name
FROM entity,attribute attribute _ 1,attribute attribute _ 2,attribute attribute_3
WHERE attribute_1.entity_id = entity.entity_id
and attribute_1.attr_id = 3
and attribute_1.value =‘女’
and attribute_1.entity_id = attribute_2.entity_id
and attribute_2.attr_id = 11
and attribute_2.attr_value = attribute_3.entity_id
and attribute_3.attr_id = 51
and attribute_3.attr_value >‘2015-01-01 00: 00: 00’
六、实验结果与分析
1、实验环境
2、实验设计
-
三种存储方案:三元组表方案、基于类型存储方案、本文提出的方案。
-
通过数据装载时间,查询响应时间,存储空间占用量来评估。
-
根据四中提出的4类查询进行测试,每条查询执行100次取平均执行时间。
3、评估与结果分析
七、结束语
总结本文研究解决的问题:
1、设计RDF三元组格式的转化方案。
2、设计面向病例知识图谱的SPARQL-to-SQL查询转换算法。
下一步研究方向:如何处理时间类型的数据。本文对于时间的查询需要使用相关的时间处理函数,导致了查询效率降低。