圖數據庫對於表現和遍歷複雜的實體之間關係是頗有效果的。而這些在傳統的關係型數據庫中尤爲是對於報表而言很難實現。若是把傳統關係型數據庫比作火車的話,那麼到如今大數據時代,圖數據庫可比作高鐵。它已成爲NoSQL中關注度最高,發展趨勢最明顯的數據庫。伴隨SQL Server 2017的出現,在SQL Server上面有了專門的圖數據庫,那麼以往須要其餘數據庫或者效率低下地處理這些工做,如今是否可讓咱們容易的實現了那?node
接下來我會用三個篇幅介紹SQLServer 圖數據庫以及它的優缺點。sql
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-ssmspost
建立模型大數據
下圖是一個關係型實體的模型,以此做爲比較:spa
若是想要比較,可使用下面的腳本建立,或者直接建立圖模型。可是,須要用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)
圖模型
圖模型的計劃與關係型模型徹底不一樣。表在圖模型中多是邊或者節點。咱們須要決定哪些表是邊,哪些表是節點。
圖具備以下特徵:
下圖表現了圖模型:
如圖所示,在模型中節點和邊很容易肯定:邏輯模型中的全部實體就是節點,而全部關係就是邊。這裏有「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。這個簡稱字段實際上是一個假的名字,稱之爲「僞列」(能夠理解爲別名),咱們能在查詢中使用。
如圖,插入數據到節點表:咱們只須要忽略$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。
建立邊表
這個操做很簡單,邊表有屬性,屬性就是表中的常規字段。腳本以下:
Create table dbo.[Written_By] as EDGE CREATE TABLE [dbo].[Likes] AS EDGE CREATE TABLE [dbo].[Reply_To] AS EDGE
每一個邊表有三個僞列,咱們須要處理:
注意這個定義,最爲重要的一點就是:咱們須要用一種合乎邏輯的方式定義 $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
這些選擇沒有技術限制,但咱們須要在插入新記錄時保留它們,永遠不要混淆關係的每一方的含義。
注意
除了三個僞列之外,全部的表表都有額外字段,而且全是隱藏字段。咱們能夠在字段屬性中看到隱藏的定義,而且這些隱藏字段不會出如今查詢結果中。
插入邊記錄
插入邊表的語句須要邊的兩端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