❶ 層次模型中的幾個術語,什麼是根結點,雙親結點,兄弟結點,葉結點
在層次模型中,資料庫中有且僅有一個記錄型無雙親,稱為根節點;同一雙親的子結點稱為兄弟結點;沒有子結點的結點稱為葉結點;代表兩個記錄型之間一對多的關系叫做雙親關系。
用樹型(層次)結構表示實體類型及實體間聯系的數據模型稱為層次模型。在樹中,每個結點表示一個記錄類型,結點間的連線或邊表示記錄類型間的關系,每個記錄類型可包含若干個欄位,記錄類型描述的是實體,欄位描述實體的屬性,各個記錄類型及其欄位都必須命名。
如果要存取某一記錄型的記錄,可以從根節點起,按照有向數層次向下查表。
(1)圖資料庫中什麼用於描述結點擴展閱讀
層次模型的數據操縱主要有查詢、插入、刪除和更新。進行插入、刪除、更新操作時要滿足層次模型的完整性約束條件。具體如下:
1、進行插入數據時,如果沒有相應的雙親結點值就不能插入它的子結點值。例如,在上圖層次資料庫中,如果新調入一名教師,但尚未分配到某個教研室,這時就不能將新的教師插入到資料庫中。
2、進行刪除數據時,如果刪除雙親結點值,則相應的子結點值也被同時刪除。例如,在上圖中的層次資料庫中,如果刪除網路教研室,則該教研室的所有教師的數據將全部丟失。
3、進行修改數據時,進行更新操作時,應更新所有相應記錄,以保證數據的一致性。
❷ 資料庫中數據流程圖是用於描述結構化方法中哪一階段的工具
作業3一、填空1.關系模型是由數據結構,數據操作,(
)三部分組成。2.關系資料庫中,二維表稱為一個(
),表的一行稱為(
),表的一列稱為(
)。3.Access提供兩種常見的創建資料庫的方法:一種是使用(
),另一種是自定義創建資料庫。
4.Access中有兩種數據類型:文本型和(
)型,他們可以保存文本或文本和數字組合的數據。5.篩選數據可以6.窗體的最基本功能是(
)數據將不符合篩選條件的數據記錄從屏幕中淘汰出去,篩選方法有四種,分別為按(
)、按選擇內容篩選、輸入篩選和高級篩選。7.在窗體設計過程中,經常要使用的三種屬性是(
)、控制項屬性和節屬性。8.Access資料庫文件的擴展名是(
)。9.SQL全稱為(
)。
10.報表預覽有列印預覽和(
)兩種視圖。二.選擇1.下面,不屬於Access查詢的是(
)
A.更新查詢
B.交叉表查詢
C.SQL查詢
D.連接查詢2.條件中「Between
70
and
90」的意思是(
)A.數值70到90之間的數字
B.數值70和90這兩個的數字
C.數值70和90這兩個的數字之外的數字D.數值70和90包含這兩個數字,並且除此之外的數字3.在查詢中對一個欄位指定的多個條件的取值之間滿足(
)關系。
A.And
B.Or
C.Not
D.Like4.在關系資料庫中,任何二元關系模式的最高範式必定是(
)
A.1NF
B.2NF
C.3NF
D.BCNF5.數據流程圖是用於描述結構化方法中(
)階段的工具。
A.可行性分析
B.詳細設計
C.需求分析
D.程序編碼6.在資料庫的概念設計中,最常用的數據模型是(
)
A.形象模型
B.物理模型
C.邏輯模型
D.實體-聯系模型7.E-R圖是資料庫設計的工具之一,它適用於建立資料庫的(
)
A.概念模型
B.邏輯模型
C.結構模型
D.物理模型8.資料庫概念設計的E-R方法中,用屬性描述實體的特徵。屬性在E-R圖中用(
)表示。A.菱形
B.矩形
C.四邊形
D.橢圓形三、簡答1.說明視圖與基本表的區別和聯系?2.並發控制可能會產生哪幾類數據不一致?用什麼方法能避免各種不一致的情況?3.什麼是規范化?答:
❸ 比Redis好用的NoSQL
實際上為了更好的描述實體之間的關系,我們要是再繼續使用Redis的話,是不是感覺實體之間的關系不夠那麼的明顯,雖然也是屬於NoSQL的一種,但是相對來說,Redis,表現實體之間的關系就沒有那麼清晰了,為了更好的描述實體之間的關系,就會使用圖形資料庫來進行了,那麼今天阿粉介紹的,就是一個圖形化的數據可,Neo4J。
Neo4j是一個世界領先的開源的基於圖的資料庫。 它是使用Java語言完全開發的。那麼什麼是圖資料庫呢?圖資料庫是以圖結構的形式存儲數據的資料庫。 它以節點,關系和屬性的形式存儲應用程序的數據。正如RDBMS以表的「行,列」的形式存儲數據,GDBMS以圖的形式存儲數據。
RDBMS與圖資料庫的區別
1.Tables 表Graphs 圖表
2.Rows 行Nodes 節點
3.Columns and Data 列和數據 Properties and its values屬性及其值
4.Constraints 約束Relationships 關系
5.Joins 加入Traversal 遍歷
說完了圖形資料庫,我們就來看看這個 Neo4J 資料庫吧
neo4j是用Java語言編寫的圖形資料庫,運行時需要啟動JVM進程,因此,需安裝JAVA SE的JDK。關於 Java 怎麼安裝,我就不用再多廢話了吧,到時候別忘了檢測一下 Java 的版本就好了, java -version
接下來我們就是要進行一個安裝了,我們先去官網,下載社區版,企業版要收費的,注意哈。
官網地址
下載完成,直接開始安裝,傻瓜式操作即可。
Neo4j應用程序有如下主要的目錄結構:
注意,如果你使用的是Zip的壓縮包來進行的使用的話,那麼你就需要注意一些地方,比如你如果是用 Zip 的包解壓之後,並且想要通過 bat 的命令啟動,直接在目錄下進行 cmd ,然後 neo4j.bat ,這時候可能會出現一個問題,就是版本可能會出現問題,你如果下載使用的是最新版的 Neo4J ,那麼就可能會讓你使用 JDK 11 ,而阿粉就是踩過了這個大坑之後,才發現,bat 閃退的原因。
這樣就是說明我們的 JDk 的版本對應的和 Neo4J 需要的 JDK 是不匹配的,我們就需要換一下我們的 JDK 了。把他換成 JDK 11 就好了,再次啟動。
這時候,我們就直接訪問 localhost:7474 的埠,直接就能看到如下的畫面, 1.jpg
剛進入的時候可能需要大家輸入帳號密碼,默認的帳號密碼就是,neo4j 修改成你想要的就行了。
這樣登錄進去我們就能開始正式學習 Neo4J 的所有內容了。
Neo4j - CQL語法
我們在講語法之前首先我們先得看看 Neo4J 的構建模塊,不然之後的查詢都是無意義的。
Neo4j圖資料庫主要有以下構建塊 -
節點是圖表的基本單位。 它包含具有鍵值對的屬性,如下所示
屬性是用於描述圖節點和關系的鍵值對
關系是圖形資料庫的另一個主要構建塊。 它連接兩個節點,如下所示。
Label將一個公共名稱與一組節點或關系相關聯。 節點或關系可以包含一個或多個標簽。 我們可以為現有節點或關系創建新標簽。 我們可以從現有節點或關系中刪除現有標簽。
Neo4j數據瀏覽器 一旦我們安裝Neo4j,我們可以訪問Neo4j數據瀏覽器使用以下URL
http:// localhost:7474 / browser /
CREATE 語法
CREATE ( : )
它是我們要創建的節點名稱。
它是一個節點標簽名稱
我們可以創建一個節點,然後給他安排上一個標簽
CREATE (emp:Employee)
當我們看到
Added 1 label, created 1 node, completed after 74 ms.
這就創建成功了,
那麼怎麼查看呢?
MATCH語法
MATCH ( : ) return xxx
是這個樣子的
但是看到裡面竟然沒有東西,就相當於是一個空的對象,那是不是就應該給裡面放入屬性的操作呢?沒錯,肯定有
CREATE (emp:Employee{ id : 1001 ,name :"lucy", age : 10})
Added 1 label, created 1 node, set 3 properties, completed after 163 ms. 創建成功。
我們再次查看就能看到
如果我們想只要其中的一些對象的屬性,而不是全部屬性,那應該怎麼操作呢?
RETURN語法
RETURN 可以返回的是一個對象,也可以是對象中的屬性,比如:
結果就是下面這個樣子的,大家看一下,是不是感覺還是挺好用的。
** WHERE語法**
WHERE
為什麼在前面的位置阿粉說,CQL 是和 SQL 類型的,這完全是因為很多東西和 SQL 是類似的。
結果如下:
相同的還有
布爾運算符 描述 AND 和 OR 或者 NOT 非 XOR 異或
比較運算符 描述 = 「等於」運算符 > 「不等於」運算符 < 「小於」運算符 > 「大於」運算符 <= 「小於或等於」運算符。 >= 「大於或等於」運算符。
DELETE語法
刪除語法必然是有的,因為有創建,肯定有刪除。
DELETE
但是這個命令也不是單獨使用的哈,
MATCH (e: Employee) DELETE e
直接刪除成功。
基礎的東西講完了,阿粉就得說說這個比較重要的內容了,關系,
我們之前創建節點的時候,那叫一個簡單舒適加愉快,但是創建關系就比較復雜了,因為需要考慮如何匹配到有關系的兩個節點,以及關系本身的屬性如何設置。這里我們就簡單學一下如何建立節點之間的關系。
由於Neo4j CQL語法是以人類可讀的格式。 Neo4j CQL也使用類似的箭頭標記來創建兩個節點之間的關系。
每個關系( )包含兩個節點
在Neo4j中,兩個節點之間的關系是有方向性的。 它們是單向或雙向的。
如果我們嘗試創建一個沒有任何方向的關系,那麼就會報錯。
關系創建語法
CREATE ( )-[ ]->( )
我們這里直接使用創建新的節點來創建關系。
提示創建成功
這里關系名稱是「CONTAINS」
關系標簽是「contains」。
這么看是看不出有啥關系的,但是,我們可以從另外的一個位置
這樣看下來,這個 Neo4J 簡單操作是不是就學會了,阿粉接下來的文章中講怎麼使用 Java 來操作 Neo4J 資料庫。歡迎大家來觀看。
❹ 圖資料庫的應用有哪些優點
圖形資料庫每個對象是一個節點,之間的關系是一條邊。相對於關系資料庫來說,圖形資料庫善於處理大量復雜、互連接、低結構化的數據,這些數據變化迅速,需要頻繁的查詢——在關系資料庫中,由於這些查詢會導致大量的表連接,從而導致性能問題,而且在設計使用上也不方便。
圖形資料庫適合用於社交網路,推薦系統等專注於構建關系圖譜的系統。
圖資料庫的代表有Neo4J、FlockDB、InfoGrid、AllegroGraph、GraphDB等。
❺ 如何用 Python 實現一個圖資料庫(Graph Database)
本文章是 重寫 500 Lines or Less 系列的其中一篇,目標是重寫 500 Lines or Less 系列的原有項目:Dagoba: an in-memory graph database。
Dagoba 是作者設計用來展示如何從零開始自己實現一個圖資料庫( Graph Database )。該名字似乎來源於作者喜歡的一個樂隊,另一個原因是它的前綴 DAG 也正好是有向無環圖 ( Directed Acyclic Graph ) 的縮寫。本文也沿用了該名稱。
圖是一種常見的數據結構,它將信息描述為若干獨立的節點( vertex ,為了和下文的邊更加對稱,本文中稱為 node ),以及把節點關聯起來的邊( edge )。我們熟悉的鏈表以及多種樹結構可以看作是符合特定規則的圖。圖在路徑選擇、推薦演算法以及神經網路等方面都是重要的核心數據結構。
既然圖的用途如此廣泛,一個重要的問題就是如何存儲它。如果在傳統的關系資料庫中存儲圖,很自然的做法就是為節點和邊各自創建一張表,並用外鍵把它們關聯起來。這樣的話,要查找某人所有的子女,就可以寫下類似下面的查詢:
還好,不算太復雜。但是如果要查找孫輩呢?那恐怕就要使用子查詢或者 CTE(Common Table Expression) 等特殊構造了。再往下想,曾孫輩又該怎麼查詢?孫媳婦呢?
這樣我們會意識到,SQL 作為查詢語言,它只是對二維數據表這種結構而設計的,用它去查詢圖的話非常笨拙,很快會變得極其復雜,也難以擴展。針對圖而言,我們希望有一種更為自然和直觀的查詢語法,類似這樣:
為了高效地存儲和查詢圖這種數據結構,圖資料庫( Graph Database )應運而生。因為和傳統的關系型資料庫存在極大的差異,所以它屬於新型資料庫也就是 NoSql 的一個分支(其他分支包括文檔資料庫、列資料庫等)。圖資料庫的主要代表包括 Neo4J 等。本文介紹的 Dagoba 則是具備圖資料庫核心功能、主要用於教學和演示的一個簡單的圖資料庫。
原文代碼是使用 JavaScript 編寫的,在定義調用介面時大量使用了原型( prototype )這種特有的語言構造。對於其他主流語言的用戶來說,原型的用法多少顯得有些別扭和不自然。
考慮到本系列其他資料庫示例大多是用 Python 實現的,本文也按照傳統,用 Python 重寫了原文的代碼。同樣延續之前的慣例,為了讓讀者更好地理解程序是如何逐步完善的,我們用迭代式的方法完成程序的各個組成部分。
原文在 500lines 系列的 Github 倉庫中只包含了實現代碼,並未包含測試。按照代碼注釋說明,測試程序位於作者的另一個代碼庫中,不過和 500lines 版本的實現似乎略有不同。
本文實現的代碼參考了原作者的測試內容,但跳過了北歐神話這個例子——我承認確實不熟悉這些神祇之間的親緣關系,相信中文背景的讀者們多數也未必了解,雖然作者很喜歡這個例子,想了想還是不要徒增困惑吧。因此本文在編寫測試用例時只參考了原文關於家族親屬的例子,放棄了神話相關的部分,盡管會減少一些趣味性,相信對於入門級的代碼來說這樣也夠用了。
本文實現程序位於代碼庫的 dagoba 目錄下。按照本系列程序的同意規則,要想直接執行各個已完成的步驟,讀者可以在根目錄下的 main.py 找到相應的代碼位置,取消注釋並運行即可。
本程序的所有步驟只需要 Python3 ,測試則使用內置的 unittest , 不需要額外的第三方庫。原則上 Python3.6 以上版本應該都可運行,但我只在 Python3.8.3 環境下完整測試過。
本文實現的程序從最簡單的案例開始,通過每個步驟逐步擴展,最終形成一個完整的程序。這些步驟包括:
接下來依次介紹各個步驟。
回想一下,圖資料庫就是一些點( node )和邊( edge )的集合。現在我們要做出的一個重大決策是如何對節點/邊進行建模。對於邊來說,必須指定它的關聯關系,也就是從哪個節點指向哪個節點。大多數情況下邊是有方向的——父子關系不指明方向可是要亂套的!
考慮到擴展性及通用性問題,我們可以把數據保存為字典( dict ),這樣可以方便地添加用戶需要的任何數據。某些數據是為資料庫內部管理而保留的,為了明確區分,可以這樣約定:以下劃線開頭的特殊欄位由資料庫內部維護,類似於私有成員,用戶不應該自己去修改它們。這也是 Python 社區普遍遵循的約定。
此外,節點和邊存在互相引用的關系。目前我們知道邊會引用到兩端的節點,後面還會看到,為了提高效率,節點也會引用到邊。如果僅僅在內存中維護它們的關系,那麼使用指針訪問是很直觀的,但資料庫必須考慮到序列化到磁碟的問題,這時指針就不再好用了。
為此,最好按照資料庫的一般要求,為每個節點維護一個主鍵( _id ),用主鍵來描述它們之間的關聯關系。
我們第一步要把資料庫的模型建立起來。為了測試目的,我們使用一個最簡單的資料庫模型,它只包含兩個節點和一條邊,如下所示:
按照 TDD 的原則,首先編寫測試:
與原文一樣,我們把資料庫管理介面命名為 Dagoba 。目前,能夠想到的最簡單的測試是確認節點和邊是否已經添加到資料庫中:
assert_item 是一個輔助方法,用於檢查字典是否包含預期的欄位。相信大家都能想到該如何實現,這里就不再列出了,讀者可參考 Github 上的完整源碼。
現在,測試是失敗的。用最簡單的辦法實現資料庫:
需要注意的是,不管添加節點還是查詢,程序都使用了拷貝後的數據副本,而不是直接使用原始數據。為什麼要這樣做?因為字典是可變的,用戶可以在任何時候修改其中的內容,如果資料庫不知道數據已經變化,就很容易發生難以追蹤的一致性問題,最糟糕的情況下會使得數據內容徹底混亂。
拷貝數據可以避免上述問題,代價則是需要佔用更多內存和處理時間。對於資料庫來說,通常查詢次數要遠遠多於修改,所以這個代價是可以接受的。
現在測試應該正常通過了。為了讓它更加完善,我們可以再測試一些邊緣情況,看看資料庫能否正確處理異常數據,比如:
例如,如果用戶嘗試添加重復主鍵,我們預期應拋出 ValueError 異常。因此編寫測試如下:
為了滿足以上測試,代碼需要稍作修改。特別是按照 id 查找主鍵是個常用操作,通過遍歷的方法效率太低了,最好是能夠通過主鍵直接訪問。因此在資料庫中再增加一個字典:
完整代碼請參考 Github 倉庫。
在上個步驟,我們在初始化資料庫時為節點明確指定了主鍵。按照資料庫設計的一般原則,主鍵最好是不具有業務含義的代理主鍵( Surrogate key ),用戶不應該關心它具體的值是什麼,因此讓資料庫去管理主鍵通常是更為合理的。當然,在部分場景下——比如導入外部數據——明確指定主鍵仍然是有用的。
為了同時支持這些要求,我們這樣約定:欄位 _id 表示節點的主鍵,如果用戶指定了該欄位,則使用用戶設置的值(當然,用戶有責任保證它們不會重復);否則,由資料庫自動為它分配一個主鍵。
如果主鍵是資料庫生成的,事先無法預知它的值是什麼,而邊( edge )必須指定它所指向的節點,因此必須在主鍵生成後才能添加。由於這個原因,在動態生成主鍵的情況下,資料庫的初始化會略微復雜一些。還是先寫一個測試:
為支持此功能,我們在資料庫中添加一個內部欄位 _next_id 用於生成主鍵,並讓 add_node 方法返回新生成的主鍵:
接下來,再確認一下邊是否可以正常訪問:
運行測試,一切正常。這個步驟很輕松地完成了,不過兩個測試( DbModelTest 和 PrimaryKeyTest )出現了一些重復代碼,比如 get_item 。我們可以把這些公用代碼提取出來。由於 get_item 內部調用了 TestCase.assertXXX 等方法,看起來應該使用繼承,但從 TestCase 派生基類容易引起一些潛在的問題,所以我轉而使用另一個技巧 Mixin :
實現資料庫模型之後,接下來就要考慮如何查詢它了。
在設計查詢時要考慮幾個問題。對於圖的訪問來說,幾乎總是由某個節點(或符合條件的某一類節點)開始,從與它相鄰的邊跳轉到其他節點,依次類推。所以鏈式調用對查詢來說是一種很自然的風格。舉例來說,要知道 Tom 的孫子養了幾只貓,可以使用類似這樣的查詢:
可以想像,以上每個方法都應該返回符合條件的節點集合。這種實現是很直觀的,不過存在一個潛在的問題:很多時候用戶只需要一小部分結果,如果它總是不計代價地給我們一個巨大的集合,會造成極大的浪費。比如以下查詢:
為了避免不必要的浪費,我們需要另外一種機制,也就是通常所稱的「懶式查詢」或「延遲查詢」。它的基本思想是,當我們調用查詢方法時,它只是把查詢條件記錄下來,而並不立即返回結果,直到明確調用某些方法時才真正去查詢資料庫。
如果讀者比較熟悉流行的 Python ORM,比如 SqlAlchemy 或者 Django ORM 的話,會知道它們幾乎都是懶式查詢的,要調用 list(result) 或者 result[0:10] 這樣的方法才能得到具體的查詢結果。
在 Dagoba 中把觸發查詢的方法定義為 run 。也就是說,以下查詢執行到 run 時才真正去查找數據:
和懶式查詢( Lazy Query )相對應的,直接返回結果的方法一般稱作主動查詢( Eager Query )。主動查詢和懶式查詢的內在查找邏輯基本上是相同的,區別只在於觸發機制不同。由於主動查詢實現起來更加簡單,出錯也更容易排查,因此我們先從主動查詢開始實現。
還是從測試開始。前面測試所用的簡單資料庫數據太少,難以滿足查詢要求,所以這一步先來創建一個更復雜的數據模型:
此關系的復雜之處之一在於反向關聯:如果 A 是 B 的哥哥,那麼 B 就是 A 的弟弟/妹妹,為了查詢到他們彼此之間的關系,正向關聯和反向關聯都需要存在,因此在初始化資料庫時需要定義的邊數量會很多。
當然,父子之間也存在反向關聯的問題,為了讓問題稍微簡化一些,我們目前只需要向下(子孫輩)查找,可以稍微減少一些關聯數量。
因此,我們定義數據模型如下。為了減少重復工作,我們通過 _backward 欄位定義反向關聯,而資料庫內部為了查詢方便,需要把它維護成兩條邊:
然後,測試一個最簡單的查詢,比如查找某人的所有孫輩:
這里 outcome/income 分別表示從某個節點出發、或到達它的節點集合。在原作者的代碼中把上述方法稱為 out/in 。當然這樣看起來更加簡潔,可惜的是 in 在 Python 中是個關鍵字,無法作為函數名。我也考慮過加個下劃線比如 out_.in_ 這種形式,但看起來也有點怪異,權衡之後還是使用了稍微啰嗦一點的名稱。
現在我們可以開始定義查詢介面了。在前面已經說過,我們計劃分別實現兩種查詢,包括主動查詢( Eager Query )以及延遲查詢( Lazy Query )。
它們的內在查詢邏輯是相通的,看起來似乎可以使用繼承。不過遵循 YAGNI 原則,目前先不這樣做,而是只定義兩個新類,在滿足測試的基礎上不斷擴展。以後我們會看到,與繼承相比,把共同的邏輯放到資料庫本身其實是更為合理的。
接下來實現訪問節點的方法。由於 EagerQuery 調用查詢方法會立即返回結果,我們把結果記錄在 _result 內部欄位中。雖然 node 方法只返回單個結果,但考慮到其他查詢方法幾乎都是返回集合,為統一起見,讓它也返回集合,這樣可以避免同時支持集合與單結果的分支處理,讓代碼更加簡潔、不容易出錯。此外,如果查詢對象不存在的話,我們只返回空集合,並不視為一個錯誤。
查詢輸入/輸出節點的方法實現類似這樣:
查找節點的核心邏輯在資料庫本身定義:
以上使用了內部定義的一些輔助查詢方法。用類似的邏輯再定義 income ,它們的實現都很簡單,讀者可以直接參考源碼,此處不再贅述。
在此步驟的最後,我們再實現一個優化。當多次調用查詢方法後,結果可能會返回重復的數據,很多時候這是不必要的。就像關系資料庫通常支持 unique/distinct 一樣,我們也希望 Dagoba 能夠過濾重復的數據。
假設我們要查詢某人所有孩子的祖父,顯然不管有多少孩子,他們的祖父應該是同一個人。因此編寫測試如下:
現在來實現 unique 。我們只要按照主鍵把重復數據去掉即可:
在上個步驟,初始化資料庫指定了雙向關聯,但並未測試它們。因為我們還沒有編寫代碼去支持它們,現在增加一個測試,它應該是失敗的:
運行測試,的確失敗了。我們看看要如何支持它。回想一下,當從邊查找節點時,使用的是以下方法:
這里也有一個潛在的問題:調用 self.edges 意味著遍歷所有邊,當資料庫內容較多時,這是巨大的浪費。為了提高性能,我們可以把與節點相關的邊記錄在節點本身,這樣要查找邊只要看節點本身即可。在初始化時定義出入邊的集合:
在添加邊時,我們要同時把它們對應的關系同時更新到節點,此外還要維護反向關聯。這涉及對字典內容的部分復制,先編寫一個輔助方法:
然後,將添加邊的實現修改如下:
這里的代碼同時添加正向關聯和反向關聯。有的朋友可能會注意到代碼略有重復,是的,但是重復僅出現在該函數內部,本著「三則重構」的原則,暫時不去提取代碼。
實現之後,前面的測試就可以正常通過了。
在這個步驟中,我們來實現延遲查詢( Lazy Query )。
延遲查詢的要求是,當調用查詢方法時並不立即執行,而是推遲到調用特定方法,比如 run 時才執行整個查詢,返回結果。
延遲查詢的實現要比主動查詢復雜一些。為了實現延遲查詢,查詢方法的實現不能直接返回結果,而是記錄要執行的動作以及傳入的參數,到調用 run 時再依次執行前面記錄下來的內容。
如果你去看作者的實現,會發現他是用一個數據結構記錄執行操作和參數,此外還有一部分邏輯用來分派對每種結構要執行的動作。這樣當然是可行的,但數據處理和分派部分的實現會比較復雜,也容易出錯。
本文的實現則選擇了另外一種不同的方法:使用 Python 的內部函數機制,把一連串查詢變換成一組函數,每個函數取上個函數的執行結果作為輸入,最後一個函數的輸出就是整個查詢的結果。由於內部函數同時也是閉包,盡管每個查詢的參數形式各不相同,但是它們都可以被閉包「捕獲」而成為內部變數,所以這些內部函數可以採用統一的形式,無需再針對每種查詢設計額外的數據結構,因而執行過程得到了很大程度的簡化。
首先還是來編寫測試。 LazyQueryTest 和 EagerQueryTest 測試用例幾乎是完全相同的(是的,兩種查詢只在於內部實現機制不同,它們的調用介面幾乎是完全一致的)。
因此我們可以把 EagerQueryTest 的測試原樣不變拷貝到 LazyQueryTest 中。當然拷貝粘貼不是個好注意,對於比較冗長而固定的初始化部分,我們可以把它提取出來作為兩個測試共享的公共函數。讀者可參考代碼中的 step04_lazy_query/tests/test_lazy_query.py 部分。
程序把查詢函數的串列執行稱為管道( pipeline ),用一個變數來記錄它:
然後依次實現各個調用介面。每種介面的實現都是類似的:用內部函數執行真正的查詢邏輯,再把這個函數添加到 pipeline 調用鏈中。比如 node 的實現類似下面:
其他介面的實現也與此類似。最後, run 函數負責執行所有查詢,返回最終結果;
完成上述實現後執行測試,確保我們的實現是正確的。
在前面我們說過,延遲查詢與主動查詢相比,最大的優勢是對於許多查詢可以按需要訪問,不需要每個步驟都返回完整結果,從而提高性能,節約查詢時間。比如說,對於下面的查詢:
以上查詢的意思是從孫輩中找到一個符合條件的節點即可。對該查詢而言,主動查詢會在調用 outcome('son') 時就遍歷所有節點,哪怕最後一步只需要第一個結果。而延遲查詢為了提高效率,應在找到符合條件的結果後立即停止。
目前我們尚未實現 take 方法。老規矩,先添加測試:
主動查詢的 take 實現比較簡單,我們只要從結果中返回前 n 條記錄:
延遲查詢的實現要復雜一些。為了避免不必要的查找,返回結果不應該是完整的列表( list ),而應該是個按需返回的可迭代對象,我們用內置函數 next 來依次返回前 n 個結果:
寫完後運行測試,確保它們是正確的。
從外部介面看,主動查詢和延遲查詢幾乎是完全相同的,所以用單純的數據測試很難確認後者的效率一定比前者高,用訪問時間來測試也並不可靠。為了測試效率,我們引入一個節點訪問次數的概念,如果延遲查詢效率更高的話,那麼它應該比主動查詢訪問節點的次數更少。
為此,編寫如下測試:
我們為 Dagoba 類添加一個成員來記錄總的節點訪問次數,以及兩個輔助方法,分別用於獲取和重置訪問次數:
然後瀏覽代碼,查找修改點。增加計數主要在從邊查找節點的時候,因此修改部分如下:
此外還有 income/outcome 方法,修改都很簡單,這里就不再列出。
實現後再次運行測試。測試通過,表明延遲查詢確實在效率上優於主動查詢。
不像關系資料庫的結構那樣固定,圖的形式可以千變萬化,查詢機制也必須足夠靈活。從原理上講,所有查詢無非是從某個節點出發按照特定方向搜索,因此用 node/income/outcome 這三個方法幾乎可以組合出任意所需的查詢。
但對於復雜查詢,寫出的代碼有時會顯得較為瑣碎和冗長,對於特定領域來說,往往存在更為簡潔的名稱,例如:母親的兄弟可簡稱為舅舅。對於這些場景,如果能夠類似 DSL (領域特定語言)那樣允許用戶根據專業要求自行擴展,從而簡化查詢,方便閱讀,無疑會更為友好。
如果讀者去看原作者的實現,會發現他是用一種特殊語法 addAlias 來定義自己想要的查詢,調用方法時再進行查詢以確定要執行的內容,其介面和內部實現都是相當復雜的。
而我希望有更簡單的方法來實現這一點。所幸 Python 是一種高度動態的語言,允許在運行時向類中增加新的成員,因此做到這一點可能比預想的還要簡單。
為了驗證這一點,編寫測試如下:
無需 Dagoba 的實現做任何改動,測試就可以通過了!其實我們要做的就是動態添加一個自定義的成員函數,按照 Python 對象機制的要求,成員函數的第一個成員應該是名為 self 的參數,但這里已經是在 UnitTest 的內部,為了和測試類本身的 self 相區分,新函數的參數增加了一個下劃線。
此外,函數應返回其所屬的對象,這是為了鏈式調用所要求的。我們看到,動態語言的靈活性使得添加新語法變得非常簡單。
到此,一個初具規模的圖資料庫就形成了。
和原文相比,本文還缺少一些內容,比如如何將資料庫序列化到磁碟。不過相信讀者都看到了,我們的資料庫內部結構基本上是簡單的原生數據結構(列表+字典),因此序列化無論用 pickle 或是 JSON 之類方法都應該是相當簡單的。有興趣的讀者可以自行完成它們。
我們的圖資料庫實現為了提高查詢性能,在節點內部存儲了邊的指針(或者說引用)。這樣做的好處是,無論資料庫有多大,從一個節點到相鄰節點的訪問是常數時間,因此數據訪問的效率非常高。
但一個潛在的問題是,如果資料庫規模非常大,已經無法整個放在內存中,或者出於安全性等原因要實現分布式訪問的話,那麼指針就無法使用了,必須要考慮其他機制來解決這個問題。分布式資料庫無論採用何種數據模型都是一個棘手的問題,在本文中我們沒有涉及。有興趣的讀者也可以考慮 500lines 系列中關於分布式和集群演算法的其他一些文章。
本文的實現和系列中其他資料庫類似,採用 Python 作為實現語言,而原作者使用的是 JavaScript ,這應該和作者的背景有關。我相信對於大多數開發者來說, Python 的對象機制比 JavaScript 基於原型的語法應該是更容易閱讀和理解的。
當然,原作者的版本比本文版本在實現上其實是更為完善的,靈活性也更好。如果想要更為優雅的實現,我們可以考慮使用 Python 元編程,那樣會更接近於作者的實現,但也會讓程序的復雜性大為增加。如果讀者有興趣,不妨對照著去讀讀原作者的版本。
❻ 圖資料庫的應用場景
TranswarpStellarDB是自主研發的分布式圖資料庫,兼容openCypher查詢語言,提供海量圖數據的存儲和分析能力,支持原生圖存儲結構,支持萬億邊PB級數據存儲。同時,StellarDB具備毫秒級點邊查詢能力,10+層的深度鏈路分析能力,提供近40種的圖分析演算法,具備數據2D和3D展示能力。星環科技StellarDB在金融、政府和社交網路等領域應用,並且在某地電信關系圖譜場景實現了萬億邊規模的存儲和穩定運行,真正意義上將萬億級圖資料庫能力應用落地。
圖資料庫典型應用場景:
知識圖譜:
於圖資料庫而言,知識圖譜是圖資料庫關聯最為緊密、應用范圍最廣的應用場景。知識圖譜對海量信息進行智能化處理,形成大規模的知識庫並進而支撐業務應用。
知識圖譜中圖資料庫具有存儲和查詢兩方面的技術優勢:存儲方面:圖資料庫提供了靈活的設計模式;查詢方面:圖資料庫提供了高效的關聯查詢
作為圖資料庫的底層應用,知識圖譜可為多種行業提供服務,具體應用場景例如電商、金融、法律、醫療、智能家居等多個領域的決策系統、推薦系統、智能問答等。
風險合規知識圖譜:風險是金融的命脈,也是國家監管科技的主幹。金融監管+風險合規的知識圖譜是星環科技最早開始投入建設和技術研發的方向。面向超大規模圖網路,星環科技率先發布了支持空間3D的圖展示,避免了二維圖的展示對於超過萬節點的圖無法清晰體現的弊端;同時結合反洗錢網路圖譜利用屬性圖中節點帶有地理定位屬性,構建了跨境可疑資金轉正圖網路,對於可疑跨境交易一目瞭然。
精準營銷類知識圖譜:大型金融機構可能存在上千萬家的B端或者C端用戶,如何實現針對不同用戶的精準營銷?在營銷知識圖譜方面,星環科技面向銀行開發了對公知識圖譜的技術,實現了在營銷端沉澱業務知識,充分發揮圖譜價值,幫助銀行實現諸如疫情期間小微企業信貸精準投放等應用。
投資研究類支持圖譜:在金融和資本市場,最重要的金融業務就是投資,利用知識圖譜刻畫人類研究成果,進行知識圖譜化表達和構建,也是多家券商和基金公司在探索金融科技賦能投資收益效果的發展路線圖。在投資知識圖譜方面,星環科技通過全棧能力,深度融合NLP+知識圖譜技術,通過知識表示學習等領先的知識圖譜技術,實現智能投研知識圖譜,賦能投資研究場景應用。
金融領域
在金融領域,圖資料庫通過利用多維交叉關聯信息可以深度刻畫交易行為,可以有效識別規模化、隱蔽性的欺詐網路,結合機器學習、聚類分析、風險傳播等相關演算法,可以實時計算用戶的風險評分,在風險行為發生前預先識別,有效幫助金融機構提升效率、降低風險。
反欺詐:通過賬戶、交易、電話、IP地址、地理位置等關鍵實體信息的關聯關系,對風險暴露人的N層圖挖掘,幫助篩選疑似欺詐人員,達到預防目的。
反欺詐信貸擔保圈:中小企業通過關聯企業、產業鏈上下遊客戶、關系人等相互擔保,形成關系復雜的「擔保網」,信貸擔保圈的挖掘對企業貸款風險的識別與防範有重要意義。
股權穿透:通常是由高管、企業及關聯公司構成的復雜網路,以股權為紐帶,向上穿透到目標企業最終實際控制人,向下穿透到該企業任意層股權投資的所有企業及其股東。
圖資料庫更多應用場景
金融領域:冒名貸款、銀行零售知識圖譜、銀行對公知識圖譜、資金流向分析、企業關聯圖譜、事件傳遞圖譜、個人信貸反欺詐、反洗錢知識圖譜等
政企領域 :物聯網、智慧城市、道路規劃、智能交通、軌跡分析、疫情防控、寄遞關系畫像等
電信領域:深度經營分析、防騷擾、電信詐騙防範、運營商經營分析等
零售領域:智能推薦、精準營銷、供應鏈管理、貨物推薦、瀏覽軌跡分析等
社交領域:社區發現、好友推薦、興趣用戶推薦、輿論跟蹤等
工業領域:電網分析、供應鏈管理、設備管理、物流分析等
醫療領域:智能診斷、電子病歷、醫保&保險分析等
❼ 什麼是圖資料庫
圖資料庫(Graph database) 並非指存儲圖片的資料庫,而是以「圖」這種數據結構存儲和查詢數據。目前比較典型的代表產品是Neo4j。
❽ 圖形資料庫與語義的關系
語義的核心是圖形資料庫。
圖形資料庫用於語義查詢的圖形結構(如節點、邊和屬性)來表示和存儲數據。
圖形資料庫是一種在線資料庫管理系統,具有處理圖形數據模型的創建,讀取,更新和刪除操作。
❾ 資料庫節點是什麼
資料庫節點:
單節點就是資料庫軟體安裝在一台伺服器上。
雙節點就是資料庫軟體安裝在兩台伺服器上,可能是為高可用,或者負載均衡來考慮的,比如oracle 的RAC,一般就是雙節點。
多節點就是資料庫軟體安裝在多台伺服器上,這樣形成更大的集群,其中每一台安裝有資料庫軟體的伺服器就叫一個節點。
比較一下網路節點的概念,你就清楚了:
每一台連上網路的計算機都是一個網路節點
整個網路就是由這許許多多的網路節點組成的
❿ 資料庫都有哪些
常用資料庫有mysql、oracle、sqlserver、sqlite等。mysql性能較好,適用於所有平台,是當前最流行的關系型資料庫之一。sqlserver資料庫具有擴展性和可維護性,且安全性較高,是比較全面的資料庫。