图数据库(txt+pdf+epub+mobi电子书下载)


发布时间:2021-03-10 22:39:36

点击下载

作者:美]伊恩·罗宾逊(Ian Robinson),吉姆·韦伯(Jim Webber),埃米尔·艾弗雷姆(Emil Eifrem)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

图数据库

图数据库试读:

前言

图数据库应对的是当今一个宏观商业世界的大趋势:凭借高度关联的数据中复杂而动态的联系获得洞察力并赢得竞争优势。无论我们想了解的是客户之间的联系,电话或数据中心网络元素之间的联系,娱乐产品制作者和消费者之间的联系,还是基因和蛋白质之间的联系,都会涉及大量的高度关联的数据。这些数据又会构成庞大的图,而理解和分析这些图的能力将成为公司在未来十年的核心竞争力。

对于任何达到一定规模或价值的数据,图数据库都是呈现和查询这些关联数据的最好方式。关联数据是这样的一种数据:它需要我们首先理解它的组成元素之间的关联方式。为了理解这个,很多时候我们需要去给这些事物之间的关联加以命名和限定。

尽管在一段时间以前一些大公司就已经意识到这个问题,并着手开发各自专有的图处理技术,但我们正处在一个技术全民化的时代。现如今,通用的图数据库已经成为现实,主流用户不必去投资建设自己的图架构,就可以享受关联数据带来的好处。

这次图数据和图思考复兴的伟大之处正在于图论本身并不是一个新事物。自18世纪欧拉创建了图论以来,数学家、社会学家、人类学家和其他领域工作者一直在研究和完善图论。然而,图论和图思考在信息管理中的应用却是最近几年的事情。那个时候,图数据库已经在社交网络、主数据管理(master data management)、地理空间、推荐系统以及其他领域帮我们解决了许多重要问题。有两股力量驱动我们对图数据库的日益关注:一股力量是那些获得巨大商业成功的公司,如Facebook、Google和Twitter,他们都将自己的商业模式紧紧地围绕在他们专有的图技术上;另一股力量就是通用的图数据库开始进入到技术领域里。关于本书

本书的目的是为技术实践者介绍图和图数据库,包括开发人员、数据库专业人士和技术决策者。阅读本书将会让你对图数据库有一个贴近实际的理解。我们将演示图模型如何“塑造”数据,以及如何用图数据库查询、推断、理解和处理数据。我们讨论了多种适合用图数据库处理的问题,配以从实际应用中提取的用户案例,还将展示如何规划和实施一个图数据库解决方案。本书的排版约定

本书使用下列排版约定。● 中文楷体:用于新术语、邮件地址、文件名称以及文件扩展名。● 等宽字体:用于程序代码,包括文字段落中引用的程序元素,如

变量、函数名、数据库、数据类型、环境变量、代码语句和关键

字。● 加粗等宽字体:用于命令以及其他需要用户逐字输入的文字。● 等宽斜体:应该由用户提供的值或根据上下文确定的值。此图标表示一个提示、建议或一般性注释。此图标表示警告或慎用。代码示例的使用

这本书的目的是帮助你完成工作。一般来说,如果这本书包括代码示例,你可以在你的程序和文档中使用本书的代码。你不需要联系我们申请权限,除非你要直接复制相当大的一部分代码。例如,在编写程序的过程中使用了本书中的几段代码,这不需要授权。售卖或者分发O'Reilly的图书示例光盘显然是需要授权的。引用本书或引用示例代码来回答问题是不需要授权的,但将本书的大量示例代码纳入产品的文档是需要授权的。

我们对你在使用时声明引用信息表示赞赏,但并不做强制要求。引用信息通常包括书名、作者、出版社和ISBN,如“Graph Databases by Ian Robinson, Jim Webber, and Emil Eifrem (O'Reilly). Copyright 2013 Neo Technoogy, Inc., 978-1-449-35626-2”。

如果你认为对示例代码的使用需要授权,请通过这个邮箱联系我们:permissions@oreilly.com。联系我们

如果你想就本书发表评论或有任何疑问,敬请联系出版社。

美国:

O'Reilly Media Inc.1005 Gravenstein Highway NorthSebastopol, CA 95472

中国:

北京市西城区西直门南大街2号成铭大厦C座807室(100035)奥莱利技术咨询(北京)有限公司我们为本书提供了专门的网页,上面有勘误表、示例,以及其他额外的信息,可以通过http://oreil.ly/graph-databases访问该网页。

为本书提供建议和咨询技术问题,请发送邮件到bookquestions@oreilly.com。

想了解更多关于我们的书籍、课程、会议,以及新闻等信息,请登录我们的网站:http://www.oreilly.com。

我们的其他联系方式如下。

Facebook: http://facebook.com/oreilly

Twitter: http://twitter.com/oreillymedia

YouTube:http://www.youtube.com/oreillymedia致谢

我们要感谢本书的技术审稿人Michael Hunger、Colin Jack、Mark Needham和Pramod Sadalage。

我们赞赏并感谢本书的编辑Nathan Jepson。

在本书成书的过程中,Neo Technology的同事极大地贡献了他们的时间、经验和努力。特别感谢Anders Nawroth对本书的工具组提供了宝贵的帮助;感谢Andrés Taylor对Cypher部分提供的热情帮助;感谢Philip Rathle对行文提供的建议和所做的贡献。

感谢Neo4j社区的所有人,感谢你们这些年对图数据库做出的许多贡献。

还要特别感谢我们的家人Lottie、Tiger、Elliot、Kath、Billy、Madelene和Noomi,谢谢他们付出的爱和支持。第1章简介

虽然本书大部分内容是讨论图数据模型的,但这并不是一本关于[1]图论的书。使用图数据库并不需要太多的理论知识:只要知道什么是图就够了。记住这一点,下面来大体回顾一下我们对图的认识。1.1 图是什么

说得正式一点儿,图仅仅是顶点和边的集合,或者说更简单一点儿,图就是一些节点和关联这些节点的联系(relationship)的集合。图将实体表现为节点,实体与其他实体连接的方式表现为联系。我们可以用这个通用的、富有表现力的结构来建模各种场景,从宇宙火箭的建造到道路系统,从食物的供应链及原产地追踪到人们的病历,甚至更多其他的场景。无处不在的图

在我们了解科学、政府和商业领域的数据集广泛多样性的过程中,图起到了极大的作用。现实世界完全不同于关系型数据库背后的基于表的模型,它是丰富的且相互之间充满关联:有些部分是统一而规则的,而其他部分是特殊的、不规则的。一旦理解了图,你就会发现图无处不在。比如,Gartner定义了商业世界的5个图—社交、意向、消费、兴趣和移动,并指出运用这些图的能力是一个“可持续的竞争优势”。

就拿Twitter来说,它的数据很容易表示为一张图。在图1-1中我们可以看到由互相关注的人组成的一个小的社交网络。联系是这里建立语义上下文的关键,也就是说,Billy关注了(FOLLOWS)Harry,反过来,Harry也关注了Billy,Ruth和Harry同样也是互相关注的,但是,尽管Ruth关注了Billy,但Billy却对他无动于衷。图1-1 一个小型社交图

当然,实际的Twitter图比图1-1要大数亿倍,但它们的工作原理是一样的。在图1-2中,我们把Ruth发布的消息也包含到图里面来。图1-2 发布消息

尽管图很简单,但图1-2还是展示出了图模型的表现力。我们很容易从中看出Ruth发布了一连串的消息。通过标记为CURRENT的联系可以找到最新的一条消息;PREVIOUS联系建立了消息时间线。属性图模型

在讨论图1-2的过程中,我们也顺便提一下一个最流行的图模型变体—属性图(property graph)(在附录A中我们会更详细地讨论其他可替代的图数据模型)。属性图具有如下特征。● 它包含节点和联系。● 节点上有属性(键值对)。● 联系有名字和方向,并总是有一个开始节点和一个结束节

点。● 联系也可以有属性。

对于大部分人来说,属性图模型是直观且容易理解的。不过简单归简单,使用图将有价值的见解融入到数据中的大多数场景却都可以用属性图来描述。1.2 图领域概览

近年来,无数用于管理、处理和分析图的项目和产品纷纷涌入市场。技术选择的陡增使我们难以跟进这些工具并摸清它们之间的区别,即便对我们这些一直活跃在这个领域的人来说也是如此。本节的内容对理解新兴的图领域提供了一个“高空俯览”。

从1万英尺高空往下看,我们可以将图领域划分成以下两部分。用于联机事务图的持久化技术通常直接实时地从应用程序中访问

这类技术被称为图数据库,正是本书主要讨论的内容。它们和“通常的”关系型数据库世界中的联机事务处理(online transactional processing,OLTP)数据库是一样的。用于离线图分析的技术通常都是按照一系列步骤执行的

这类技术被称为图计算引擎。它们可以和其他大数据分析技术看做一类,如数据挖掘和联机分析处理(online analytical processing,OLAP)。我们可以从另一个视角去划分图领域,去观察各种技术使用的图模型。主流的图模型有3种,分别是属性图、资源描述框架(Resource Description Framework,RDF)三元组和超图。我们将会在附录A中对它们进行详细的说明。市场上常见的大多数图数据库使用的都是属性图模型,因此,在本书的剩余部分我们也将使用这一模型。1.2.1 图数据库

图数据库管理系统(以下将简称图数据库)是一种在线的数据库管理系统,它支持对图数据模型的增、删、改、查(CRUD)方法。图数据库一般用于事务(OLTP)系统中。相应地,它们也对事务性能进行了优化,在设计时通常考虑了事务完整性和操作可用性。

在研究图数据库技术时,有两个特性需要多加考虑。底层存储

一些图数据库使用原生图存储,这类存储是优化过的,并且是专门为了存储和管理图而设计的。不过并不是所有图数据库使用的都是原生图存储,也有一些图数据库会将图数据序列化,然后保存到关系型数据库或面向对象数据库,或是其他通用数据存储中。处理引擎

一些定义要求图数据库使用免索引邻接,这意味着,关联节点在[2]数据库中物理意义上“指向”彼此。如果看得更远一点:站在用户的角度,任何看起来像是图数据库的都可以称为图数据库(比如说,提供了对图数据模型的CRUD操作的数据库)。然而,我们得承认这个事实,免索引邻接带来巨大的性能优势是其他数据库无法比拟的,因此我们使用原生图处理来代表使用免索引邻接的图数据库。需要注意的是,原生图存储和原生图处理并不一定比其他方式更好或更差—这不过是典型的工程取舍而已。原生图存储的好处是,它的栈是专门为性能和扩展性设计建造的。但相对的,非原生图存储通常建立在非常成熟的非图后端(如MySQL)之上,运维团队对它们的特性烂熟于心。原生图处理(无索引邻接)虽然在遍历查询时性能优势很大,但代价是一些非遍历类的查询会比较困难,而且还要占用巨大的内存。

与那些需要额外增加像外键这样的属性或者使用map-reduce这样的额外处理来推测实体间关联的数据库管理系统不同,联系在图数据模型中是“一等公民”。图数据库通过将节点和联系的简单抽象组装为相互关联的结构,使我们能够建造任意复杂的模型,来形象地映射我们的问题域。比起那些传统的关系型数据库和其他NoSQL存储,我们所得到的模型更简单,也更具表现力。

根据其存储和处理模型不同,图1-3生动形象地展示了现在市场上的一些图数据库。图1-3 图数据库概览1.2.2 图计算引擎

图计算引擎技术使我们可以在大数据集上使用全局图算法。图计算引擎主要用于识别数据中的集群,或是回答类似于“在一个社交网络中,平均每个人有多少联系?”这样的问题。

因为偏重于全局查询,图计算引擎通常为扫描和批处理大规模信息做过优化,在这个方面,它们和其他批分析技术(如在关系型数据库世界中大家都很熟悉的数据挖掘和OLAP)类似。只有一部分图计算引擎有自己的图存储层,其他的(几乎可以说大部分)则只完全关注于如何处理外部传入的数据和返回结果。

图1-4展示了一个通用的图计算引擎部署架构。该架构包括一个带有OLTP属性的记录系统(SOR)数据库(如MySQL、Oracle或Neo4j),它给应用程序提供服务,请求并响应应用程序在运行中发送过来的查询。每隔一段时间,一个抽取、转换和加载(ETL)作业就会将记录系统数据库的数据转入图计算引擎,供离线查询和分析。图1-4 典型图计算引擎部署的示意图

图计算引擎多种多样。最出名的有内存的、单机的图计算引擎Cassovary和分布式的图计算引擎Pegasus和Giraph。大部分分布式图计算引擎基于Google发布的Pregel白皮书,其中讲述了Google如何使用图计算引擎来计算网页排名。本书重点关注图数据库

通过前面的部分,我们对图领域有了一个大致的了解。在这之后,本书将主要关注图数据库。我们的目标始终是试图向读者解释清楚图数据库的概念。我们会在适当的时候穿插一些例子来说明这些概念。这些例子都来自于我们使用属性图模型和Neo4j数据库开发解决方案的过程中获得的经验。读者不必在意我们的例子中使用了什么具体的图模型或图数据库,这些关键概念对于其他的图数据库同样适用。1.3 图数据库的威力

虽然事实上我们可以将任何东西都建模成图,但我们生活在一个很现实的世界里,它充满了预算限制、项目限期、企业标准,还有商业化的技术选型。图数据库提供了强大而新颖的数据建模方法,但它本身却无法为其能够替换那些已经享有盛誉并被用户充分认识的数据平台提供足够的理由。必须要有一个直接而明显的好处,人们才会使用它。对于图数据库来说,这个动机可以用一系列用例和数据模式来说明:采用图的方案,性能可以提升一个甚至几个数量级,而且比起聚合的批处理,其延迟也小很多。除此之外,图数据库还提供极其灵活的数据模型,这也和当今敏捷软件交付实践推崇的交付模式相一致。1.3.1 性能

其中一个充分的理由就是,与关系型数据库和NoSQL存储处理关联数据相比,选择图数据库会有绝对的性能提升。随着数据集的不断增大,关系型数据库处理密集join(join-intensive)查询的性能也会随之变差,而图数据库则不然。在数据集增大时,它的性能趋向于保持不变,这是因为查询总是只与图的一部分相关。因此,每个查询的执行时间只和满足查询条件的那部分遍历的图的大小(而不是整个图的大小)成正比。1.3.2 灵活性

作为开发者和数据架构师,我们希望根据问题域决定如何连接数据。这样,就不需要在对数据的真实模样和复杂度了解最少的时候,被迫预先做出决定。随着我们对问题域了解的加深,结构和schema会自己浮现出来。图数据库正中我们下怀。正如我们在第3章中将要展示的,图数据模型表示和适应业务需求的方式,使IT部门终于可以跟得上业务的变化速度。

图天生就是可扩展的,这意味着我们可以对一个已经存在的结构增加不同种类的联系、新节点和新子图,而不用担心破坏已有的查询或应用程序的功能。这些特点对于开发者的生产力和项目风险一般都有积极的意义。同时由于图模型的灵活性,我们不必在项目最初就穷思竭虑地把领域中的每一个细枝末节都考虑到模型中—这种做法在不断变化的业务需求面前,简直就是蛮干。图的天然可扩展性也意味着我们会做更少的数据迁移,从而降低维护开销和风险。1.3.3 敏捷性

通过使用与当今增量及迭代的软件交付实践相吻合的技术,我们希望能够就像改进应用程序的其他部分一样改进我们的数据模型。现代图数据库还让我们拥有平滑的开发方式,配以优雅的系统维护。尤其是图数据库天生不需要schema,再加上其API和查询语言的可测性,使我们可以用一个可控的方式来开发应用程序。

同时,正是因为图数据库不需要schema,所以它缺少以schema为导向的数据管理机制,即在关系世界中我们已经熟知的机制。但这并不是一个风险,相反,它促使我们采用了一种更可见的、可操作的管理方式。正如我们在第4章会讲到的,图数据库的管理通常作用于编程方式,利用测试来驱动数据模型和查询,以及依靠图来断言业务规则。这不再是一个有争议的做法,事实上这已经比关系型开发应用更广了。图数据库开发方式非常符合当今的敏捷软件开发和测试驱动软件开发实践,这使得以图数据库为后端的应用程序可以跟上不断变化的业务环境。1.4 小结

本章介绍了属性图模型,在表示关联数据上,它简单却传神。属性图用生动而灵活的方式捕捉复杂的领域,与此同时,图数据库则使我们可以运用图模型以更加简单的方式开发应用程序。

在下一章中,我们将更详细地探讨不同的技术是怎样应对关联数据带来的挑战的,从关系型数据库开始,到聚合NoSQL存储,最后到图数据库。在讨论的过程中,我们将看到为什么图和图数据库是建模、存储和查询关联数据的最佳方式。之后的几章将会展示如何设计和实施一个以图数据库为基础的解决方案。

[1]  关于图论的介绍,请参考Richard J. Trudeau的《Introduction to Graph Theory》(Dover,1993)和Gary Chartrand的《Introductory Graph Theory》(Dover,1985)。如果想要了解图是怎样给复杂的时间和行为提供洞察力的,请参考David Easley和Jon Kleinberg的《Networks, Crowds, and Markets: Reasoning about a Highly Connected World》(Cambridge University Press,2010)。

[2]  参考Rodriguez, M. A.和Neubauer, P.的《The Graph Traversal Pattern》(2010)。第2章关联数据的存储选择

我们生活在互联的世界中。为了发展进步,我们需要理解并影响所处的网络。

如今的技术是如何处理关联数据的呢?本章关注于关系型数据库和聚合NoSQL存储如何管理图和关联数据,并比较这些数据库或存储与图数据库在处理图和关联数据方面的性能。对NoSQL有兴趣的读者可以深入阅读附录中描述的4种主流NoSQL数据库。2.1 关系型数据库缺少联系

数十年来,开发者试图使用关系型数据库处理关联的、半结构化的数据集。关系型数据库设计之初是为了处理纸质表格以及表格化结构—有些方面关系型数据库做得非常好—它们试图对这种实际中的特殊联系进行建模。然而讽刺的是,关系型数据库在处理联系上做得却并不好。

联系确实存在于关系型数据库自身的术语中,但只是作为连接表的手段。前面章节在对关联数据的讨论中曾经提到,我们经常需要对连接实体的联系进行语义的区分,同时限制它们的使用。关联关系什么也做不了。更糟糕的是,随着离群数据(outlier data)的成倍地增加,数据集的宏观结构将愈发复杂和不规整,关系模型将造成大量表连接、稀疏行和非空检查逻辑。关系世界中连通性的增强都将转化为连接操作的增加,这会阻碍性能,并使已有的数据库难以响应变化的业务需求。

图2-1展示了一个以客户为中心的、事务型应用程序存储顾客订单的关系模式(relational schema)。

这种schema的设计对该应用程序产生了很大影响,使有些查询非常简单,而有些异常困难。● 表连接增加了偶发复杂性,使得业务数据与外键元数据混杂起

来。● 外键约束增加了额外的开发与维护成本,而目的仅仅是为了让数

据库工作。● 带有空值列的稀疏表在代码中需要额外检查,尽管schema本身

提供了相关 支持。● 仅因为想要查看客户买了什么就需要好几个昂贵的连接。● 反向查询(reciprocal query)代价更高。查询“客户买了哪些商

品?”比查询“有哪些客户买了这个商品?”的代价相对要低,

这就是推荐系统的基础。对于这样的需求,可以引入索引(index),然而即使引入索引,“有哪些买了那个商品的客户还

买了这个商品?”随着递归程度的增加,递归问题的查询代价变

得异常高昂。图2-1 语义联系隐藏在关系型数据库中

关系型数据库在强关联领域做着斗争。让我们通过社交网络领域中一些简单的和不那么简单的查询来理解关系型数据库中关联查询的成本吧。

图2-2展示了一个记录朋友关系的简单的连接表设计。图2-2 关系型数据库中对于朋友和朋友的朋友的建模

回答“谁是Bob的朋友?”这个问题很简单,如示例2-1所示。

示例2-1 Bob的朋友SELECT p1.PersonFROM Person p1 JOIN PersonFriend ON PersonFriend.FriendID = p1.IDJOIN Person p2 ON PersonFriend.PersonID = p2.IDWHERE p2.Person = 'Bob'

基于这个示例数据,答案是Alice和Zach。这不是一个代价高昂或困难的查询,因为它使用了WHERE Person.person='Bob',使得返回的行数是可预期的和有限的。

朋友关系不总是自反关系(reflexive relationship),因此在示例2-2中,需要回答示例2-1的反向查询:“谁是Bob的朋友?”

示例2-2 谁的朋友是BobSELECT p1.PersonFROM Person p1 JOIN PersonFriend ON PersonFriend.PersonID = p1.IDJOIN Person p2 ON PersonFriend.FriendID = p2.IDWHERE p2.Person = 'Bob'

这个查询的答案是Alice,很遗憾Zach不认为Bob是他的朋友。这个反向查询在实现上也很简单,但是数据库端的花销就略微大些了,因为所有的数据行都在表PersonFreiend中。

我们可以加入索引,然而仍会涉及代价高昂的间接层。当问题是“谁是我的朋友的朋友?”时就更麻烦了。SQL的层级结构使用了递归连接,这使得查询语法和计算都更加复杂,如示例2-3所示。(有些关系型数据库提供这种查询的语法糖—比如Oracle提供了函数CONNECT BY,它可以简化查询语句,但并不能降低底层的计算复杂度。)

示例2-3 Alice的朋友的朋友们SELECT p1.Person AS PERSON, p2.Person AS FRIEND_OF_FRIENDFROM PersonFriend pf1 JOIN Person p1 ON pf1.PersonID = p1.IDJOIN PersonFriend pf2 ON pf2.PersonID = pf1.FriendIDJOIN Person p2 ON pf2.FriendID = p2.IDWHERE p1.Person = 'Alice' AND pf2.FriendID <> p1.ID

即使只是处理Alice的朋友的朋友们,而不是深入Alice的整个社交网络,这个查询计算也很复杂。当我们试图探究社交网络时,问题则更复杂,代价也更高。虽然“谁是我的朋友的朋友们?”这样的问题还是可能在合理的时间内通过查询得到答案,但是当查询延伸到第4度、第5度或第6度的朋友关系时,由于递归的连表查询使此时的时间空间复杂度非常高,从而使查询的效率严重恶化。

无论试图在关系型数据库中对关联建模还是查询关联,结果都与我们的愿望完全不同。除了之前指出的查询和计算复杂度以外,我们还得去处理schema这个双刃剑。很多时候,schema被证明是死板和脆弱的。死板表现在:我们需要在创建稀疏表的同时在代码中处理异常情况—一切只是因为没有一个能够容纳我们所用到的各类数据的通用的schema。这在增加了耦合的同时也摧毁了其貌似存在的凝聚力。脆弱表现在:当应用程序发生变化时,需要增加额外的工作从一个schema迁移到另一个schema。2.2 NoSQL数据库也缺少联系

大多数NoSQL数据库—无论是键值数据库、文档数据库,还是基于列的数据库—存储的都是无关联的文档/值/列,因此很难将它们用于关联数据和图。

对这些数据库来说,一种广为认知的添加联系的策略是在某个聚合数据(aggregate)中嵌入另一个聚合数据标识符,即添加外键。然而这需要在应用层连接聚合数据,其代价极速增加。

当我们着眼于聚合存储模型(aggregate store model)时,如图2-3所示,我们联想到了联系。看到开头为user: Alice的记录中有对订单的引用order: 1234时,我们推断user: Alice和order: 1234之间存在关联。而这给了我们错误的希望:我们可以使用键值对来管理图。

在图2-3中,我们看到一些属性值确实引用了数据库中其他的聚合数据。然而将这些引用转化为可导航的结构并非是没有代价的,因为聚合数据之间的联系并非数据模型中的一等公民—多数聚合存储只是以内嵌映射结构的方式装饰在聚合数据之内。相反,应用程序使用数据库时必须从这种扁平的、无关联的数据结构中建立起联系。我们还必须确保应用程序能够随着剩余数据的变化更新或删除外部聚合引用,假如不这样做,存储将积累无用的引用,从而破坏数据的质量和查询性能。图2-3 聚合存储模型中联系的具体化Riak中的指针(Links)和查找(Walking)

Riak键值存储引擎允许使用指针(Link)元数据去扩展每个存储的值。指针都是单向的,从一个存储的值指向另一个。Riak允许查找(Walk)(Riak术语)任何数量的指针,从而一定程度上将数据模型关联起来。然而,Riak的指针查找是通过map-reduce驱动的,这一定程度上会有延迟。与图数据库不同,这种指针的连接仅适用于简单的图结构编程,对于通用的图算法就不适用了。

这种方案还有另一个弱点。由于没有反向指针(当然,外部聚合引用的指针不是自反的),数据库丧失了运行其他有趣的查询的能力。比如在图2-3中,想要知道是谁买了某种商品(也许问这个问题的目的是想要基于客户资料进行推荐)就是一个代价高昂的操作。想要回答这类问题,我们可能得通过导出数据集并在外部计算框架(如Hadoop)上运行它们来暴力地获得结果。或者只能回过头将外部聚合引用反向插入,随后才能查询结果。无论哪种方法,结果都不是直接的,都是潜在的。

人们很容易认为聚合存储和图数据在关联数据这方面的功能是等同的。但其实不是这样的。聚合存储并不维护关联数据的一致性,也不提供免索引邻接(index-free adjacency),即元素直接与其邻居相连。因此未解决数据关联问题,聚合存储必须使用天生的潜在的方法在数据模型之外创建和查询联系。

让我们看看它们的局限性是如何表现的。图2-4展示了一个使用聚合存储来实现文档存储的小型社交网络。图2-4 使用聚合存储编码的小型社交网络

通过这种结构,可以很容易地找到用户的直接朋友—假设应用程序一直在努力确保存储在friends属性中的标识符与数据库中的其他记录的ID保持一致。在这种情况下,我们可以简单地通过它们的ID检索直接朋友,这需要对每个朋友进行大量索引查找,但不需要对整个数据集暴力扫描。这样做我们会发现,Bob认为Alice和Zach是他的朋友。

但朋友关系不总是自反的。如果我们想问问“谁的朋友是Bob?”而不是“谁是Bob的朋友?”,问题就比较难以回答了。在这种情况下,我们唯一的选择是暴力扫描整个数据集,从而在所有friends条目中寻找到包含Bob的条目。O符号和暴力计算

我们用O符号作为描述一个算法的性能随数据集的大小而变化的简写方式。O(1)算法表示性能的时间复杂度为常数时间,也就是说,该算法与数据集大小无关,无论数据集大小如何,执行算法所花时间都是相同的。O(n)算法表示性能的时间复杂度为线性时间,当数据集增加一倍,执行算法所花时间也会增加一倍。O(log n)算法表示性能的时间复杂度为对数时间,当数据集增加一倍,执行算法所花时间增加一个固定的量。在起步阶段,随着数据集的增大,其所花时间的增加相对很多,但数据集变得非常大的时候,时间的增加会渐渐消失趋于稳定。O(m log n)算法表示的时间复杂度是本书所考虑的最差情况。在O(m log n)的算法中,当数据集增加一倍时,执行时间会在加倍的同时有额外的增加,其增加量与数据集中元素数目成正比。

暴力计算整个数据集的时间复杂度是O(n),因为在数据存储中所有的即n个聚合数据都需要加以考虑。这对于大多数合理规模的数据集来说代价过高,在这里我们要选择一个时间复杂度为O(log n)的算法(这很大程度上是高效的,因为它在每次迭代时能够丢弃掉一半的潜在工作量)或者复杂度更低的算法。

相反,图数据库对于同一个查询提供恒定的查找顺序。在这种情况下,我们只需在图中找到表示Bob的节点,然后寻找任何friend的入度联系,这些联系连接的节点表示那些认为Bob是他们的朋友的人。这比暴力扫描的代价小得多,因为它只和网络中很少的节点相关,即,那些和Bob关联的节点。当然,如果所有人都认为Bob是他们的朋友,我们还是会遍历到整个数据集。

为了避免处理整个数据集,我们可以增加反向指针,但这会反规范化存储模型。通过为每个用户添加另一个属性,也许可以称为friended``_``by,我们可以列出与该用户相关联的入度朋友关系。但这不是没有代价的。对于起点数据,我们要因写入延迟增加初始成本和后续成本,还要为存储额外的元数据增加磁盘使用开销。最重要的是,因为每一跳(hop)都需要通过一次索引查找,所以遍历指针的代价仍然很高。这是因为聚合数据没有局部性这个概念,它不像图数据库那样通过真实的(而不是具体化的)联系自然地提供免索引邻接。如此,通过实现图结构之上的非原生存储,我们获得了局部连通性的好处,但却引入了巨大的开销。

当遍历涉及比一跳更深的时候,这种巨大的开销被放大了。朋友关系是足够简单的,然而想象一下,当试图实时地计算朋友的朋友,或是朋友的朋友的朋友时,这类数据库就不合时宜了,因为遍历一个虚假的联系的代价并不小。这不仅限制了你扩大社交网络的机会,也减少了有益的推荐,错过数据中心的故障设备,并让欺诈采购活动成为漏网之鱼。许多系统试图去维护类图的计算处理,但仍很难避免要分批处理,并不能按照用户需求提供实时的交互。2.3 图数据库拥抱联系

前面的例子处理了隐式的关联数据。作为用户,我们推断实体之间的语义相关性,但数据模型与数据库本身却忽视这些关联。为了弥补这一点,我们的应用程序必须着手创建一个扁平的、无连接的数据之外的网络,然后再处理那些由反规范化存储导致的缓慢查询和延迟写入。

我们真正想要的是一个全景图,包括元素之间的关联。与我们之前看到的不同,在图的世界中,关联数据被存储为关联数据。业务领域中存在的关联,在数据中也有,如图2-5所示的社交网络。图2-5 在图中的朋友、同事、工人以及(单相思)恋人的简单建模

在这个社交网络中,有如此多的实际情景中的关联数据,但实体之间的关联并没有表现得与业务领域一致—领域是半结构化的。社交网络是一个非常流行的密集关联、半结构化的网络的例子,它不该被作为一个普适schema,也不该被分割成多个无关联的聚合数据。这个简单的朋友网络已经在规模上变大(潜在的朋友关系的距离已经深达6度),并且在表现力上变得丰富。图模型的灵活性使我们能增加新的节点和新的联系,与此同时不影响现有网络,也不用做数据迁移—原始数据和其意图都保持不变。

这个图为该网络提供了更丰富的信息。我们可以看到谁LOVES(爱着)谁(无论爱是否是单相思的),也可以看到谁是谁的COLLEAGUE_OF(同事),谁是所有人的BOSS_OF(老板)。我们可以看到谁没有市场了,因为他们和别人是MARRIED_TO(结婚)联系。我们甚至可以在其他社交网络中发现不善交际的元素,用DISLIKES(不喜欢)联系来表示。有了通过我们所掌握的这个图,我们现在就可以看看图数据库在处理关联数据时的性能优势了。

图中的关系自然地形成了路径。查询图或是遍历图都涉及路径。由于从根本上数据模型是面向路径的,多数基于路径的图数据库的操作都与数据本身的呈现高度一致,因此它们极为高效。在Neo4j in Action一书中,Partner和Vukotic使用关系存储和Neo4j进行实验。实验通过对比表明,在处理关联数据方面,图数据库比关系存储要快得多。

Partner和Vukotic的实验试图在一个社交网络里找到最大深度为5的的朋友的朋友。假设随机选择两个人,是否存在一条路径,使得关联他们的关系长度最多为5?对于一个包含100万人,每人约有50个朋友的社交网络,结果明显表明,图数据库是用于关联数据的最佳选择,如表2-1所示。表2-1 在关系型数据库和Neo4j中寻找扩展朋友的性能对比深关系型数据库的执行时间Neo4j的执行时间返回的记录度(s)(s)条数20.0160.01~2500330.2670.168~110 00041543.5051.359~600 0005未完成2.132~800 000

在深度为2时(即朋友的朋友),假设在一个在线系统中使用,无论关系型数据库还是图数据库,它们的执行时间都表现得足够好。虽然Neo4j的查询时间为关系数据库的2/3,但终端用户很难注意到两者间毫秒级的时间差异。当深度为3时(即朋友的朋友的朋友),很明显关系型数据库无法在合理的时间内实现查询:一个在线系统无法接受30 s的查询时间。相比之下,Neo4j的响应时间则保持相对平坦:执行查询仅需要不到1 s,这对在线系统来说足够快了。

在深度为4时,关系型数据库表现出很严重的延迟,使其无法应用于在线系统。Neo4j所花时间也有所增加,但其时延在在线系统的可接受范围内。最后,在深度为5时,关系型数据库所花时间过长以至于没有完成查询。相比之下,Neo4j则在2 s左右的时间就返回了结果。在深度为5时,事实证明几乎整个网络都是我们的朋友:因此在很多实际用例中,我们可能需要修剪结果,并进行时间控制。聚合存储和关系型数据库对于超出合理规模的集合操作表现得都不太好。当我们试图从图中挖掘路径信息时(比如朋友的朋友那个例子),操作慢了下来。我们并非想要贬低聚合存储和关系型数据库,它们在各自所擅长的方面有很好的技术能力,但在管理关联数据时却无能为力。任何超出寻找直接朋友或是寻找朋友的朋这样的浅遍历的查询,都将因为涉及的索引的数量而使查找变得缓慢。而图数据库由于使用了免索引邻接,确保了遍历关联数据是非常迅速的。

社交网络这个例子有助于说明不同的技术是如何处理关联数据的,但它是否是一个有效的用例呢?我们是否真的需要寻找这样远的“朋友”呢?也许不是。但将社交网络替换为任何其他领域时,你会发现我们在性能、建模和维护方都能面获得类似的好处。无论是音乐还是数据中心管理,无论是生物信息还是足球统计,无论是网络传感器还是时序交易,图都能对这些数据提供强有力而深入的理解。让我们来看看另一个图在当代的应用:基于用户自己的购买历史和他的朋友、邻居以及其他喜欢他的人的购买历史为他推荐商品。这个例子中,我们能将用户生活方式中多个独立的方面汇集起来,做出准确而有商业意义的推荐。图2-6 用图建模的用户订单历史

首先,我们将用户的购买历史建模为关联数据。这在图中很简单,只需将用户和她的订单链接起来,然后我们再将这些订单链接为购买历史,如图2-6所示。

图2-6所示的图深入洞察了客户行为。我们可以看到用户已经PLACED(订购)的所有订单,同时可以容易地推出每个订单CONTAINS(包含)了什么。到目前为止一切顺利,重要的是,我们丰富了图,使其能支持各种熟知的访问模式。例如,用户往往希望看到自己的订单历史,因此我们在图中增加一个链表结构,这样我们可以通过向外的MOST_RECENT(最近)联系找到用户最近的订单。随后,我们可以通过迭代该链表,沿着每个PREVIOUS(上一个)联系回溯到更早的订单。如果我们希望找到更近的订单,我们则可以反向寻找PREVIOUS联系,或者添加一个反向的NEXT(下一个)联系。

现在我们可以开始进行推荐了。如果我们发现买草莓冰淇淋的用户还购买了意大利咖啡豆,我们就可以推荐那些通常只买冰淇淋的用户也去买意大利咖啡豆。虽然我们通过遍历大量订单保证了草莓冰淇淋和咖啡豆间的强相关性,但这不只过是一个一维的推荐,我们可以做得更好。为了提高图的能力,我们可以将图与其他领域的图连接起来。由于图天然是多维结构,所以可以更直接地提问更复杂的问题,以此获得市场需要微调的部分。例如,我们可以通过图知道“住在某个用户附近、喜欢意式咖啡但不喜欢球芽甘蓝的人们所喜欢的冰淇淋的口味都有哪些?”

为了解释数据,我们需要考虑反复购买同一商品的用户在多大程度上象征着他喜欢这款商品。但如何才能定义“住在附近”?事实证明,地理坐标最应该用图来建模。最流行的表示地理坐标的结构被称为R树。R树是描述有边界区域的类图索引。使用这样的结构可以描述地理区域的重叠层次。例如,我们可以陈述一个事实,伦敦在英国,邮编为SW111BD的地方在巴特西,这是伦敦的一个区域,伦敦在英格兰的东南部,而英格兰在英国。由于英国的邮政编码粒度很细,因此可以把邮编作为标准来界定有相似口味的目标人群。在SQL中或是聚合存储中写这样的模式匹配查询都非常困难,并且其查询性能都很不好。而图数据库在这方面做了优化,能够在这类遍历和模式匹配查询方面提供精确到毫秒级别的响应。此外,多数图数据库提供了适合表达图结构和图查询的查询语言。下一章我们将讲解Cypher,这是一个适合描述图的模式匹配语言。

除了可以用例子中的图向用户进行推荐,我们还能借此使卖方获益。例如,对于某些购买模式(商品、典型订单的价格等),我们可以确定一个特定的事务是否是潜在的欺诈。通过图可以很容易地识别特定用户的非常规模式,于是能够将其标记出来并进一步关注(可以使用关于图的数据挖掘文献中的众所周知的相似性度量),从而减少卖方的风险。

从数据从业者的角度来看,很明显,图数据库是处理复杂的、半结构化的、紧密关联的数据的最好的技术,也就是说,对于如此复杂的数据,使用别的方式处理远不如使用图。2.4 小结

我们在本章已经看到,关系型数据库和NoSQL数据存储中的关联需要开发人员在应用程序层实现数据处理,而相比之下,关联在图数据库中则是一等公民。下一章我们将详细地描述图建模。第3章使用图进行数据建模

在前面的章节我们看到,无论是与文件系统、列族(column family)、键值对形式的NoSQL存储相比,还是与传统的关系型数据库相比,图数据库都具有显著的好处。一旦选择了图数据库,接下来我们就会问:如何使用图来建模呢?

本章的重点是图建模。首先我们将回顾属性图模型,也就是应用最广泛的图数据模型,随后我们将了解本书大部分的代码示例所使用的图查询语言:Cypher。Cypher是几种用来描述和查询属性图的语言之一。即便到了今天,图查询语言仍然没有一个公认的标准,如同SQL在关系型数据库管理系统中那样。我们之所以选用Cypher,有一部分原因是作者很熟悉它,此外是因为它易于学习和理解,并且已经得到了广泛的应用。在了解以上要点之后,我们会深入地看几个图建模的例子。第一个例子是在系统管理领域,在这个例子中,我们将会比较关系建模和图建模技术的区别。随后的例子是关于莎士比亚文学的生产和消费的,我们尝试用一个图来连接和查询几个不同的领域。在本章的结尾,我们会介绍一些使用图建模时常见的陷阱,并着重讲解一些最佳实践。3.1 模型和目标

在深入探讨图建模之前,我们先说一下什么是建模。建模是一种由特定的需求或目的驱动的抽象动作。建模是为了让不规则的领域的一些具体方面变成结构化的、可操纵的空间。对于事物实际存在的方式没有哪种天然的模型表示,有的只是有目的的选择、抽象和简化。为了满足某个目标,一些方法比另外一些更有用。

在这方面,用图来表示也没什么不同。图建模与其他建模技术的不同之处在于其逻辑模型和物理模型之间的密切关系。关系型数据管理技术背离了用自然的语言来描述领域:先是哄骗我们将其表述成逻辑模型,然后再生硬地将其转换成物理模型。这些转换使得概念化的世界和模型的数据库实例之间产生了语义失调。而使用图数据库,这个分歧明显地缩小了。我们已经在用图交流

我们喜欢把领域中的信息要素抽象成圆圈和方框,然后用箭头把它们连起来,以此来表达它们之间的关联。图模型正迎合了这点。不同于其他任何数据库,今天的图数据库是“对白板友好的”。一个问题的典型白板视图就是一个图。我们在白板上勾勒的创意和分析模式都可以映射成数据库中真实的数据模型。在表现力方面,图数据库减少了分析和实现之间的阻抗不匹配问题,这个问题已经困扰了关系型数据库的实现很多年了。特别有意思的一点是,图模型不仅描绘出了我们是如何思考事物之间的关系,还清晰地表达出了我们可能在这个领域中提出的问题。正如我们在本章将会看到的,图模型和图查询是一个问题的两个方面。3.2 属性图模型

第1章中介绍了属性图模型,总结起来,主要有以下几个特征。● 属性图是由节点、联系和属性组成的。● 节点上包含属性。我们可以把节点想象成存储属性的文件,

属性可以以任何键值对的形式存在。键一般是字符串,值则可以

是任意类型的数据。● 联系连接并构建节点。每个联系都拥有一个方向、一个标签、

一个开始节点和一个结束节点。没有哪个联系是放空的。总之,

联系的方向和标签使得节点的结构富有语义化。● 就像节点一样,联系也是有属性的。可以通过在联系上增加

属性给图算法提供元数据,也可以给联系增加额外的语义(包括

特性和权重),属性还用于在运行时约束查询。

这些简单的原语已经足够我们创建出复杂的、语义丰富的模型了。到现在为止,我们所有的模型都是示意图形式的。假设不讨论技术,用示意图来描述图是没什么问题的。不过一旦涉及使用数据库,我们就需要一些其他的机制来创建、操纵和查询数据:一种查询语言。3.3 查询图:Cypher简介

Cypher是一种言简意赅的图数据库查询语言。尽管它只支持Neo4j,但它和我们使用示意图来表示图的方式非常相似,因此非常适合以精确的方式程序化地描述图。正因如此,我们将在本书接下来的部分全面使用Cypher来解释图查询和图结构。Cypher可以说是最易懂的图查询语言了,对于我们学习图来说也很有帮助。一旦你学会[1]了Cypher,你对其他图查询语言也都能触类旁通。

在接下来的部分,我们将会简单地介绍一下Cypher。当然,这并不是Cypher的参考文档,我们只希望让大家对Cypher有一个简单[2]的认识。为我们深入地探索后面那些有趣的图查询场景做准备。其他查询语言

不同的图数据库有不同的查询数据的方式。很多图数据库(包括Neo4j)都支持资源描述框架RDF查询语言SPARQL,也支持必要的基于路径的查询语言Gremlin。然而本书只关注属性图和声明式的查询语言展现出的强大的表现力。因此,本书几乎只使用了Cypher。3.3.1 Cypher的理念

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载