初识SQL Server2017 图数据库(一)

初识SQL Server2017 图数据库(一)

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

背景:

  图数据库对于表现和遍历复杂的实体之间关系是很有效果的。而这些在传统的关系型数据库中尤其是对于报表而言很难实现。如果把传统关系型数据库比做火车的话,那么到现在大数据时代,图数据库可比做高铁。它已成为NoSQL中关注度最高,发展趋势最明显的数据库。伴随SQL Server 2017的出现,在SQL Server上面有了专门的图数据库,那么以往需要其他数据库或者效率低下地处理这些工作,现在是否可以让我们容易的实现了那?

  接下来我会用三个篇幅介绍SQLServer 图数据库以及它的优缺点。

介绍:

  简单定义:图数据库是NoSQL数据库的一种类型,它应用图形理论存储实体之间的关系信息。图形数据库是一种非关系型数据库,它应用图形理论存储实体之间的关系信息。最常见例子就是社会网络中人与人之间的关系。关系型数据库用于存储“关系型”数据的效果并不好,其查询复杂、缓慢、超出预期,而图形数据库的独特设计恰恰弥补了这个缺陷。

  SQL Server 2017将带来新的功能之一就是图数据库。图数据库不像关系型数据库在一张“图”内将数据表现为节点,边和属性,而是一种抽象的数据类型,通过一组顶点节点、点和边来表现关系和连接,就像一个缠结的渔网。使我们用简单的方式来表现和遍历实体间的关系。图对象被用来表示复杂的关系。一层就是一个特定的图,记录如论坛帖子和回复之间的关系,以及人与人之间的关系。多层有一个根节点(例如,论坛中的帖子和回复),但是多个图不一定有根节点(例如人们之间的关系)

  本文中,我们一起使用一个论坛数据例子,使用新型的图模型。也会比较图和关系型模型的查询复杂度。

演示环境

  SQL Server 2017 CTP 2.1下载地址: https://www.microsoft.com/en-us/sql-server/sql-server-2017

  使用SSMS 17.0,下载地址: https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms

创建模型

  下图是一个关系型实体的模型,以此作为比较:

<span>初识SQL Server2017 图数据库(一)</span>

 

  如果想要比较,可以使用下面的脚本创建,或者直接创建图模型。但是,需要用SSMS创建一个新的数据库“GraphExample”。代码如下:

create database GraphExample
  go
  -- Trying an entire graph model
  use GraphExample
  go
  create schema Forum
  go
  create table Forum.ForumMembers
  (MemberId int not null primary key Identity(1,1),
  MemberName varchar(100))
  go
  create table Forum.ForumPosts
  ([PostID] int not null primary key,
  PostTitle varchar(100),
  PostBody  varchar(100),
  OwnerID int,
  ReplyTo   int)
  go
  Create table Forum.Likes
  (MemberId int,
  PostId int)
  go
  create table Forum.LikeMember
  (MemberId int,
   LikedMemberId int)
   go
  INSERT Forum.ForumMembers values('Mike'),('Carl'),('Paul'),('Christy'),('Jennifer'),('Charlie')
  go
   
  INSERT INTO [Forum].[ForumPosts] 
             (
             [PostID]
             ,[PostTitle]
             ,[PostBody],OwnerID, ReplyTo
                   )
       VALUES
           (4,'Geography','Im Christy from USA',4,null),
             (1,'Intro','Hi There This is Carl',2,null)
  INSERT INTO [Forum].[ForumPosts] 
             (
             [PostID]
             ,[PostTitle]
             ,[PostBody],OwnerID, ReplyTo
                   )
       VALUES
          (8,'Intro','nice to see all here!',1,1),
          (7,'Intro','I''m Mike from Argentina',1,1),
           (6,'Re:Geography','I''m Mike from Argentina',1,4),
          (5,'Re:Geography','I''m Jennifer from Brazil',5,4),
                (3,'Re: Intro','Hey Paul This is Christy',4,2),
                   (2,'Intro','Hello I''m Paul',3,1)
  go
  INSERT Forum.Likes VALUES (1,4),
   (2,7),
   (2,8),
   (2,2),
   (4,5),
   (4,6),
   (1,2),
   (3,7),
   (3,8),
       (5,4)
  go
  Insert Forum.LikeMember VALUES (2,1),
   (2,3),
   (4,1),
   (4,5)

 

图模型

  图模型的计划与关系型模型完全不同。表在图模型中可能是边或者节点。我们需要决定哪些表是边,哪些表是节点。

  图具有如下特征:

    • 包含节点和边;
    • 节点上有属性(键值对);
    • 边有名字和方向,并总是有一个开始节点和一个结束节点;
    • 边也可以有属性。

  下图表现了图模型:

 <span>初识SQL Server2017 图数据库(一)</span>

  如图所示,在模型中节点和边很容易确定:逻辑模型中的所有实体就是节点,而所有关系就是边。这里有“Posts”和“Members”两个实体, ‘Reply To’, ‘Like’‘Written By’三个边。

注意

  节点和边不过是带有特殊字段的表。没有任何限制禁止我们创建常规的表之间的关系,以便将模型转化为关系和图模型的组合。

  例如,‘Written By’ ‘Posts’‘Members’的关系,可以转化为一个一对多的关系。通过创建一个边的关系表,我们可以用常规的关系表来表现所谓的图模型中的表。也就是组合模式了。

  当我们创建一个根节点实体,这个实体接收一个叫做‘$node_id’的计算字段。我们可以使用这个字段作为主键,SQL Server 允许计算字段作为主键:如果这个主键是一个JSON字段,就不适合作为主键了。因此我们的节点必须包含两个键:业务键,整型字段,以及‘$node_id’ 键,包含整型字段自增长的JSON键。

  下面为节点实体的脚本:

Use GraphExample

  go

  CREATE TABLE [dbo].[ForumMembers](

         [MemberID] [int] IDENTITY(1,1) NOT NULL,

         [MemberName] [varchar](100) NULL

  )

  AS NODE

  GO

  

  CREATE TABLE [dbo].[ForumPosts](

         [PostID] [int] NULL,

         [PostTitle] [varchar](100) NULL,

         [PostBody] [varchar](1000) NULL

  )

  AS NODE

 

注意

  在创建对象后,在对象浏览器中检查对象。或许此时注意到一个新的文件夹在‘Tables’文件夹里面叫做‘Graph’。同时也注意到自增字段的名字,尽管我们可以用简称来引用这些字段,例如$node_id,但是真实的字段名称包含了GUID。这个简称字段其实是一个假的名字,称之为“伪列”(可以理解为别名),我们能在查询中使用。

<span>初识SQL Server2017 图数据库(一)</span>

 

  如图,插入数据到节点表:我们只需要忽略$node_id,写出插入其他字段的语句即可,语句如下:

INSERT ForumMembers values ('Mike'),('Carl'),('Paul'),('Christy'),('Jennifer'),('Charlie')
  INSERT INTO [dbo].[ForumPosts]

             (

             [PostID]

             ,[PostTitle]

             ,[PostBody]

                   )

       VALUES

          (8,'Intro','nice to see all here!'),

          (7,'Intro','I''m Mike from Argentina'),

           (6,'Re:Geography','I''m Mike from Argentina'),

          (5,'Re:Geography','I''m Jennifer from Brazil'),

           (4,'Geography','Im Christy from USA'),

                (3,'Re: Intro','Hey Paul This is Christy'),

             (1,'Intro','Hi There This is Carl')

                   (2,'Intro','Hello I''m Paul')

使用查询语句可以看到ForumPosts表的结果。你会发现$node_id字段,是一个JSON字段包含了实体类型和一个自增整型ID,它就是自增长ID。

 <span>初识SQL Server2017 图数据库(一)</span>

创建边表

  这个操作很简单,边表有属性,属性就是表中的常规字段。脚本如下:

Create table dbo.[Written_By]

  as EDGE

  CREATE TABLE [dbo].[Likes]

  AS EDGE

  CREATE TABLE [dbo].[Reply_To]

  AS EDGE

  每个边表有三个伪列,我们需要处理:

  • $edge_id: 边记录的ID
  • $from_id:在边中记录的节点ID
  • $to_id:在边中记录的其他节点ID

    注意这个定义,最为重要的一点就是:我们需要用一种合乎逻辑的方式定义  $to_id and $from_id 字段对于每条边意味着什么?你可以观察之前定义的边表如何定义的边,这是一种双向的合理选择,使得我们更容易使用和理解。

以下是我们的合理定义:

Written_By:

$from_id will be the post

$to_id will be the member

Likes:

$from_id will be who likes

$to_id will be who/what is liked

Reply_To:

$from_id will be the reply to the main post

$to_id  will be the main post

这些选择没有技术限制,但我们需要在插入新记录时保留它们,永远不要混淆关系的每一方的含义。

注意

  除了三个伪列以外,所有的表表都有额外字段,并且全是隐藏字段。我们可以在字段属性中看到隐藏的定义,并且这些隐藏字段不会出现在查询结果中。

<span>初识SQL Server2017 图数据库(一)</span>

 

<span>初识SQL Server2017 图数据库(一)</span>

 

插入边记录

    插入边表的语句需要边的两端ID,$From_id and $To_id这些字段需要用$node_id的值来填充。例如,对于一个帖子的成员,‘Written_By’包含post 的$node_id 作为$From_id 并且有member的$node_id作为$To_id字段。

下面是插入语句:

Insert into Written_By ($to_id,$from_id) values

   (

   (select $node_id from dbo.ForumMembers where MemberId= 1 ),

   (select $node_id from dbo.ForumPosts where PostID=8 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=1  ),

   (select $node_id from dbo.ForumPosts where PostID=7 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId= 1 ),

   (select $node_id from dbo.ForumPosts where PostID= 6)

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=5  ),

   (select $node_id from dbo.ForumPosts where PostID=5 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=4  ),

   (select $node_id from dbo.ForumPosts where PostID=4 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=3  ),

   (select $node_id from dbo.ForumPosts where PostID=3 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=3  ),

   (select $node_id from dbo.ForumPosts where PostID=1 )

   ),

   (

   (select $node_id from dbo.ForumMembers where MemberId=3  ),

   (select $node_id from dbo.ForumPosts where PostID=2 )

   )

 

注意

  这样插入是不是感觉很麻烦?未来我们可以使用一个对象框架用以支持图对象,目前还不支持这个功能。

  插入Reply_To脚本如下:

	INSERT Reply_To ($to_id,$from_id) 
   VALUES
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 4),
         (SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 6)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 1),
         (SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 7)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 1),
         (SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 8)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 1),
         (SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 2)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 4),
         (SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 5)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 2),
(SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 3))

最后,再插入Likes:

 

INSERT Likes ($to_id,$from_id) 
   VALUES
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 4),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 1)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 7),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 2)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 8),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 2)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 2),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 2)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 5),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 4)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 6),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 4)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 2),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 1)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 7),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 3)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 8),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 3)),
   ((SELECT $node_id FROM dbo.ForumPosts WHERE PostID = 4),
         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 5))

 

Likes 边很好的说明了边的功能作用。仅仅插入几个menbers和post表的关系,但是我们可以确定在应用中成员也可能喜欢另一个成员。当然,我们也能用这个边去关联这个成员和其他成员的关系。在关系型模型中我们需要两个表完成这个操作,在图数据库我们只需要一个边。

下面我们在论坛的成员之间插入更多的Like:

INSERT Likes ($to_id,$from_id)

   VALUES

   ((SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 1),

         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 2)),

   ((SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 3),

         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 2)),

   ((SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 1),

         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 4)),

   ((SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 5),

         (SELECT $node_id FROM dbo.ForumMembers WHERE MemberID = 4))

小结

  本篇介绍了图数据库的一些简单定义和理解,概述了SQLServer2017中如何创建图数据库的基本步骤和语句。这只是一个初步版本必然有很多缺点,当然也有一些优点,下一篇我将先介绍优点再说一下有哪些不足。

参考文献:https://www.red-gate.com/simple-talk/sql/t-sql-programming/sql-graph-objects-sql-server-2017

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119614.html原文链接:https://javaforall.net

(0)
上一篇 2021年11月28日 上午10:00
下一篇 2021年11月28日 上午11:00


相关推荐

  • linux dhcp服务器搭建_如何自己搭建服务器

    linux dhcp服务器搭建_如何自己搭建服务器本篇是关于在Linux服务器上安装并配置DHCP服务器的配置教程!

    2025年7月27日
    4
  • 基于java的实验室管理系统_javaweb管理系统项目

    基于java的实验室管理系统_javaweb管理系统项目实验室设备管理系统主要包含两个用户角色,一个是超级管理员,可以进行系统的各种管理工作,一个是普通管理员,主要进入系统进行相应的信息查看工作。系统的主要功能包含有:登陆用户的信息修改,系统用户管理,使用设备的用户信息管理,实验设备管理,设备借出管理,设备维修管理,共建记录管理,实验室设备统计(图形报表的形式展示),注销退出,登陆系统。

    2022年8月31日
    4
  • 交换机背板带宽详解

    交换机背板带宽详解交换机的背板带宽 是交换机接口处理器或接口卡和数据总线间所能吞吐的最大数据量 背板带宽标志了交换机总的数据交换能力 单位为 Gbps 也叫交换带宽 一般的交换机的背板带宽从几 Gbps 到上百 Gbps 不等 一台交换机的背板带宽越高 所能处理数据的能力就越强 但同时设计成本也会越高 一般来讲 计算方法如下 1 线速的背板带宽考察交换机上所有端口能

    2026年3月16日
    2
  • 在Ubuntu上使用FreeFileSync同步文件

    在Ubuntu上使用FreeFileSync同步文件FreeFileSync可以在Windows,Linux,macOS上面运行。本文使用操作系统是Ubuntu18.04。安装FreeFileSync下载程序,并解压。$wgethttps://freefilesync.org/download/FreeFileSync_11.0_Linux.tar.gz$tarxvfFreeFileSync_11.0_Linux.tar.gz解压之后进入FreeFileSync文件夹,就可以双击运行程序了。我们可以创建一个启动器,这样我们可以从桌面运

    2022年5月16日
    46
  • Linux设备树(Device Tree)机制

    Linux设备树(Device Tree)机制目录1.设备树(DeviceTree)基本概念及作用2.设备树的组成和使用2.1.DTS和DTSI2.2.DTC2.3.DTB2.4.Bootloader3.设备树中dts、dtsi文件的基本语法3.1.chosennode3.2.aliasesnode3.3.memorynode3.4….

    2022年6月21日
    26
  • 域名怎样实现自动跳转网页_域名

    域名怎样实现自动跳转网页_域名自动转向(Auto-Redirecting),也叫自动重定向。自动跳转,指当访问用户登陆到某网站时,自动将用户转向其它网页地址的一种技术。转向的网页地址可以是网站内的其它网页,也可以是其它网站。通常情况下,浏览器会收到一个网页,该页面含有自动加载一其它网页的代码。该页面有可能在服务器端被转换,这样的话,浏览器只收到一个页面,而自动转向往往意味着浏览器收到的页面具有自动将访问用户送至其它页面的功能。

    2022年10月4日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号