全域變數是儲存資料的寶劍。 樹木。 第2部分

全域變數是儲存資料的寶劍。 樹木。 第2部分入門 - 請參閱第 1 部分。

3. 使用全域變數時的結構變體

像有序樹這樣的結構有各種特殊情況。讓我們考慮一下那些在使用全域變數時具有實際價值的內容。

3.1 特殊情況 1. 一個節點沒有分支


全域變數是儲存資料的寶劍。 樹木。 第2部分全域變數不僅可以像數組一樣使用,還可以像常規變數一樣使用。例如,作為計數器:

Set ^counter = 0  ; установка счётчика
Set id=$Increment(^counter) ;  атомарное инкрементирование

在這種情況下,全域除了它的意義之外,還可以有分支。一者並不排斥另一者。

3.2 特殊情況2.一個頂點多分支

一般來說,這是一個經典的鍵值基礎。而如果我們將一個值的元組保存為一個值,我們將得到一個非常普通的帶有主鍵的表。

全域變數是儲存資料的寶劍。 樹木。 第2部分

要在全域變數上實作表,我們必須自己根據列值產生行,然後使用主鍵將它們儲存到全域變數中。為了使讀取時能夠將字串再次分成幾列,可以使用:

  1. 分隔符號。
    Set ^t(id1) = "col11/col21/col31"
    Set ^t(id2) = "col12/col22/col32"
  2. 嚴格的方案,其中每個欄位佔用預定數量的位元組。就像關係資料庫中所做的那樣。
  3. 一個特殊的函數 $LB(在快取中可用),它會建立一個值的字串。
    Set ^t(id1) = $LB("col11", "col21", "col31")
    Set ^t(id2) = $LB("col12", "col22", "col32")

有趣的是,使用全域變數來做類似關係型資料庫中二級索引的事情並不困難。我們將這種結構稱為索引全域變數。索引全域是一個輔助樹,用於快速搜尋不屬於主全域主鍵的欄位。要填寫並使用它,您需要編寫額外的程式碼。

讓我們在第一列上建立一個全域索引。

Set ^i("col11", id1) = 1
Set ^i("col12", id2) = 1

現在,為了快速搜尋第一列中的信息,我們必須查看全局 ^i 並找出與第一列的所需值對應的主鍵(id)。

插入值時,我們可以立即為所需欄位建立值和索引全域變數。為了可靠性,讓我們將所有內容封裝在一個事務中。

TSTART
Set ^t(id1) = $LB("col11", "col21", "col31")
Set ^i("col11", id1) = 1
TCOMMIT

有關如何在 M 上執行此操作的詳細信息 全域變數表, 二級指標模擬.

如果插入/更新/刪除行的函數是用 COS/M 編寫並編譯的,則此類表的運行速度將與傳統資料庫中一樣快(甚至更快)。我透過對一個兩個列表的批次 INSERT 和 SELECT 測試檢查了此語句,包括使用 TSTART 和 TCOMMIT 命令(事務)。

我還沒有測試過具有並發存取和並行事務的更複雜的場景。

在不使用事務的情況下,插入率為每百萬值 778 次插入/秒。
擁有 300 億個值 - 每秒 422 次插入。

使用交易時 - 572M 插入每秒 082 次插入。所有操作均透過編譯的 M 程式碼執行。
硬碟是普通硬碟,不是SSD。帶回寫入功能的 RAID5。 Phenom II 1100T 處理器。

要以類似的方式測試 SQL 資料庫,您需要編寫一個將在循環中執行插入的預存程序。在測試 MySQL 5.5(InnoDB 儲存)時,使用此方法我每秒收到的插入次數不超過 11K。
是的,全域表的實作看起來比關聯式資料庫中的表更複雜。因此,全域變數上的工業資料庫具有 SQL 存取權限,以簡化表格資料的處理。

全域變數是儲存資料的寶劍。 樹木。 第2部分一般來說,如果資料模式不會頻繁更改,插入速度並不重要,並且整個資料庫可以輕鬆地以規範化表的形式表示,那麼使用 SQL 會更容易,因為它提供了更高層級的抽象。

全域變數是儲存資料的寶劍。 樹木。 第2部分在這個特殊的例子中我想表明 全域變數可以充當創建其他資料庫的建構函數。就像可以編寫其他語言的組譯程式一樣。以下是如何在全域變數上建立類似物的範例 鍵值、清單、集合、表格、面向文件的資料庫。

如果您需要以最少的努力創建某種非標準資料庫,那麼您應該考慮全域變數。

3.3 特殊情況3.二層樹,第二層的每個節點都有固定數量的分支

全域變數是儲存資料的寶劍。 樹木。 第2部分您可能猜到了:這是全域表的另一種實作。讓我們將這個實作與先前的實作進行比較。

兩級樹上的表與兩級樹上的表在單層樹上。

缺點
優點

  1. 插入速度較慢,因為您需要將節點數設定為等於列數。
  2. 消耗更多磁碟空間。由於具有列名的全域索引(理解為數組索引)會佔用磁碟空間,並且每行都會重複。

  1. 更快地存取各個列的值,因為不需要解析字串。根據我的測試,在 11,5 列速度提高了 2%,在更多列上速度提高了更多。
  2. 更容易變更資料模式
  3. 程式碼更清晰

結論: 並不適合所有人。由於速度是全域變數最關鍵的好處之一,因此使用此實作沒有什麼意義,因為它的執行速度很可能不會比關聯式資料庫中的表快。

3.4 一般情況。樹和有序樹

任何可以表示為樹的資料結構都非常適合全域變數。

3.4.1 具有子對象的對象

全域變數是儲存資料的寶劍。 樹木。 第2部分

這是全域變數傳統使用的領域。醫學領域有大量的疾病、藥物、症狀和治療方法。為每個患者建立一個包含一百萬個欄位的表格是不合理的。而且,99%的欄位都是空的。

想像一個 SQL 資料庫表:「病患」~ 100 個字段,「醫學」- 000 個字段,「治療」- 100 個字段,「併發症」- 000 個字段,等等。等等。或者,您可以建立一個包含數千個表的資料庫,每個表針對特定類型的患者(它們可以重疊!)、治療、藥物以及用於這些表之間連接的數千個表。

全局變數對於醫學來說是理想的選擇,因為它們允許您以樹的形式為每個患者創建其病史、各種療法和藥物作用的準確描述,而無需在空列上浪費額外的磁碟空間,就像關係案例中的情況就是這樣。

全域變數是儲存資料的寶劍。 樹木。 第2部分使用全域變數可以方便地建立包含人員資料的資料庫,當累積和系統化盡可能多的有關客戶的各種資訊非常重要時。醫學、銀行、行銷、歸檔和其他領域對此有需求

.
當然,在 SQL 中你也可以模擬一棵只有幾個表格的樹(伊夫, 1,2,3,4,5,6,7,8,9,10),但是這要複雜得多並且速度會更慢。本質上,您必須編寫一個適用於表的全域變量,並將所有與表相關的工作隱藏在抽象層下。使用進階技術(SQL)來模擬低階技術(全域)是錯誤的。不當。

眾所周知,更改巨型表上的資料模式(ALTER TABLE)可能需要相當長的時間。例如,MySQL 透過將舊表中的資訊完全複製到新表來執行 ALTER TABLE ADD|DROP COLUMN(經過測試的 MyISAM、InnoDB 引擎)。這可能會使包含數十億筆記錄的工作資料庫掛起數天甚至數週。

全域變數是儲存資料的寶劍。 樹木。 第2部分如果我們使用全域變量,那麼改變資料結構就不會產生任何成本。 我們可以隨時在層次結構的任何層級的任何物件中新增所需的任何新屬性。與重新命名分支相關的變更可以在正在執行的資料庫的背景執行。


因此,當涉及到儲存具有大量可選屬性的物件時,全域變數是一個不錯的選擇。

此外,讓我提醒您,對任何屬性的存取都是即時的,因為在全域中所有路徑都是 B 樹。

一般來說,全域資料庫是一種面向文件的資料庫,能夠儲存分層資訊。因此,以文件為導向的資料庫可以在儲存醫療記錄領域與全域資料庫競爭。 但還是不太一樣我們拿MongoDB來比較一下。 在這個域中 它輸給全球的原因如下:

  1. 文檔大小。 儲存單元是JSON格式的文字(更準確地說是BSON),最大容量約為16MB。此限制是專門進行的,以便在 JSON 資料庫中儲存龐大的 JSON 文件然後透過欄位存取時,JSON 資料庫在解析過程中不會變慢。該文件應包含有關患者的所有資訊。我們都知道患者記錄有多厚。 16MB 的最大卡片大小立即終止了患者疾病卡包含 MRI 檔案、X 光掃描和其他研究的情況。在全球的一個分支中,您可以擁有千兆位元組和兆位元組的資訊。原則上,我們可以結束這種情況,但我會繼續。
  2. 病患病歷中新屬性的意識/改變/刪除時間。 這樣的資料庫必須將整個映射讀入記憶體(這是一個很大的量!),解析BSON,添加/更改/刪除新節點,更新索引,將其打包到BSON中,並將其保存到磁碟。全域變數只需要存取特定的屬性並對其進行操作。
  3. 快速存取各個屬性。 對於文件中的許多屬性及其多層結構,由於全域中的每個路徑都是 B 樹,因此對各個屬性的存取會更快。在 BSON 中,您必須線性解析文件才能找到所需的屬性。

3.3.2 關聯數組

關聯數組(即使是巢狀數組)非常適合全域變數。例如,PHP 中的這樣一個陣列將顯示在第一張圖片 3.3.1 中。

$a = array(
  "name" => "Vince Medvedev",
  "city" => "Moscow",
  "threatments" => array(
    "surgeries" => array("apedicectomy", "biopsy"),
    "radiation" => array("gamma", "x-rays"),
    "physiotherapy" => array("knee", "shoulder")
  )
);

3.3.3 分層文件:XML、JSON

也可以輕鬆儲存在全域變數中。可以以不同的方式佈置以進行存放。

XML的
將 XML 分解為全域變數的最簡單方法是將標記屬性儲存在節點中。如果需要快速存取標籤屬性,那麼我們可以將它們移到單獨的分支中。

全域變數是儲存資料的寶劍。 樹木。 第2部分

<note id=5>
<to>Вася</to>
<from>Света</from>
<heading>Напоминание</heading>
<body>Позвони мне завтра!</body>
</note>

在 COS 上,這對應於代碼:

Set ^xml("note")="id=5"
Set ^xml("note","to")="Саша"
Set ^xml("note","from")="Света"
Set ^xml("note","heading")="Напоминание"
Set ^xml("note","body")="Позвони мне завтра!"

備註: 對於 XML、JSON、關聯數組,您可以想出許多不同的全域顯示方式。在這種情況下,我們沒有在註釋標籤中反映子標籤的順序。全球範圍 ^xml 子標籤將按字母順序顯示。為了嚴格反映順序,您可以使用例如以下顯示:

全域變數是儲存資料的寶劍。 樹木。 第2部分
JSON。
3.3.1 節中的第一張圖片顯示了此 JSON 文件的反映:

var document = {
  "name": "Vince Medvedev",
  "city": "Moscow",
  "threatments": {
    "surgeries": ["apedicectomy", "biopsy"],
    "radiation": ["gamma", "x-rays"],
    "physiotherapy": ["knee", "shoulder"]
  },
};

3.3.4 透過層次關係連結的相同結構

範例:銷售辦事處的結構、傳銷結構中人員的位置、國際象棋中的空缺資料庫。

首次推出資料庫。 您可以使用行程力估計值作為全域節點的索引值。然後,為了選擇最強的動作,選擇權重最大的分支就足夠了。在全域中,每個層級的所有分支都會依照移動強度進行排序。

全域變數是儲存資料的寶劍。 樹木。 第2部分

銷售辦事處的結構,傳銷人員的結構。 節點可以儲存一定的反映整個子樹特性的快取值。例如,給定子樹的銷量。任何時候我們都可以得到一個反映任何分支機構所取得的成就的數字。

全域變數是儲存資料的寶劍。 樹木。 第2部分

4. 在什麼情況下使用全域變數最有利?

第一列介紹了透過使用全域變數可以顯著提高速度的情況,第二列介紹了設計或資料模型得到簡化的情況。

速度
易於數據處理/呈現

  1. 插入[每層自動排序]、[按主鍵索引]
  2. 刪除子樹
  3. 具有大量需要單獨存取的嵌套屬性的對象
  4. 分層結構能夠繞過任何分支的子分支,甚至是不存在的分支
  5. 子樹的深度優先遍歷
  1. 具有大量可選[和/或嵌套]屬性/實體的物件/實體
  2. 無模式數據。當新的屬性經常出現而舊的屬性消失時。
  3. 您需要建立一個自訂資料庫。
  4. 路徑庫和決策樹。當可以方便地將路徑表示為樹時。
  5. 不使用遞歸刪除層次結構

延期 「全域變數是儲存資料的寶劍。稀疏數組。第 3 部分”.

免責聲明: 本文以及我對其的評論僅代表我的觀點,與 InterSystems Corporation 的官方立場無關。

來源: www.habr.com

添加評論