【最佳實踐】分佈式數據庫關聯查詢優化與最佳實踐

 

1 前言

    分佈式數據庫從過去成爲NoSQL的數據庫發展開始,底層的數據存儲結構變得多樣化,包括KV、文檔、列式等結構。各自有本身擅長的業務應用場景,例如操做型和分析型就是最簡單的區分。shell

 

    然而SQL的支持成爲了業界的共識。 SQL語言幾十年的發展已經很是成熟,技術基礎也很是普遍。全世界90%以上的開發,不管業務操做型仍是分析型都以SQL的數據處理爲主。不管底層數據存儲結構是關係型仍是非關係型都將對系統開發透明。開發者只需根據本身的業務場景來選擇合適的數據庫,但不須要改變自身的開發模式。數據庫

 

本篇文章主要是向你們介紹分佈式數據庫的關聯查詢基本原理,以及用戶在使用SequoiaSQL作關聯查詢時應該注意哪些地方,也但願用戶可以經過本篇文章瞭解到更多分佈式數據庫操做的相關知識,同時幫助用戶快速掌握SequoiaSQL的開發和使用技巧。緩存

2 關聯查詢介紹

2.1 關聯查詢在傳統數據庫使用

在關係型數據庫中若是要介紹關聯查詢,那麼必然會涉及到數據庫範式設計的內容。那麼爲何關係型數據庫會有範式設計這種開發理念,這還得從關係型數據庫的發展歷程提及。服務器

關係型數據庫是從上世紀70年代開始發展起來的,那個時候硬件設備的成本價格是很是高的,那個時候像十幾MB的存儲硬件就已是頂配級別了,即便到了90年代,硬盤的存儲空間也就是達到幾百兆級別,價格依然昂貴。架構

因此關係型數據庫是在一個存儲資源極度緊張的背景下誕生的,在這種狀況下,數據庫研發的理念理所固然的往「儘量利用存儲空間」方向發展,一樣使用數據庫的用戶也一樣想盡辦法往數據庫中多存儲有價值數據庫。分佈式

資深的DBA明白,要想數據存儲冗餘低,那麼遵循範式設計是很是有效的方法。工具

範式設計,核心思想就是儘量確保表中每一列的數據都不會產冗餘,例如第一範式裏要求數據庫表中全部字段值都是不可分解的原子值,第二範式裏要求數據庫表中的每列都和主鍵相關,第三範式裏要求數據庫表中消除與主鍵之間的間接相關。oop

2.2 關聯的做用

因爲關係型數據庫的範式設計開發理念,因此會致使過去建設一個完整的系統,會有比較複雜的數據模型,可能一個系統會包含幾十甚至上百張數據表,而每張表之間都有主外建關聯關係。性能

在這種數據模型下,用戶若是要在系統中查詢某些數據,則可能須要同時用到幾張表甚至是幾十張表的數據纔可以獲得完整的結果集。因此要在這種遵循範式設計的系統中操做數據表,就難以免須要用到數據庫的關聯方法。學習

2.3 常見關聯查詢策略

在傳統的關係型數據庫中,最多見的關聯策略有三種,分別是:NL Join(Nest Loop Join)、Hash Join和Merge Join。

1)NL Join

NL Join的技術原理相對來講比較好理解,實際上讀者能夠理解爲兩張表一條記錄一條記錄地做比對,若是符合關聯條件則關聯成功。

 

 

使用僞代碼來表示則是

for (int i=0; i<t1.length; ++i) {

   for (int j=0; j<t2.length; ++j) {

      if ( t1[i] == t2[j] ) {

         return ( t1[i], t2[j] )

      }

   }

}

在沒有索引狀況作NL Jion,複雜度爲O(N*M)。

NL Join關聯方法一般使用在

1) 左表(也叫驅動表、外部表)數據量較小

2) 右表(也叫探查表、內部表)中匹配字段支持索引查詢,而且可以作高效查詢

典型的SQL命令以下

for (int i=0; i<t1.length; ++i) {

   for (int j=0; j<t2.length; ++j) {

      if ( t1[i] == t2[j] ) {

         return ( t1[i], t2[j] )

      }

   }

}

2)Hash Join

Hash Join的技術原理是將其中一張記錄較少的數據表加載到Hash Table上,再經過遍歷另一張表的數據,經過對關聯字段作Hash後對Hash Table上的數據作關聯匹配,若是匹配成功,則證實該記錄符合關聯條件,不然繼續讀取下一條記錄作關聯。

該方法主要利用Hash Table的分區以及內存提高匹配速度,用戶須要確保服務器的內容足以緩存下數據量較少的表的全部數據,不然超出部分將須要寫入到磁盤的臨時文件上。所以用戶能夠在內存不足狀況下,考慮採用SSD存儲來提高臨時文件的讀寫性能。

在內存足夠的狀況下,Hash Join 的複雜度僅僅爲O(N+M)

因此Hash Join主要使用的場景是

1) 關聯的表數據量較大

2) 機器內存足以緩存所有或者絕大部分關聯數據

3) 只能用在等值匹配關聯匹配上

典型的SQL命令以下

select t1.name,t2.info

    from t1,t2

    where t1.id=t2.id;

3)Merge Join

Merge Join也被稱爲Sort Merge Join,顧名思義,就是要對須要關聯的表根據關聯字段作排序後再作匹配關聯計算。

 

Merger Join的實現步驟比較複雜,讀者能夠理解爲程序同時對兩張已經排好序的表從頭開始讀取匹配字段的值,若是二者值不相同,則一方選擇下一個值繼續匹配,若是匹配成功,則一方讀取下一個值繼續匹配,直至任意一張表的全部數據讀取完畢,匹配程序結束。

例如SQL引擎要對t1和t2兩張表作Merge Join,兩表的排序方式爲升序排序,Merge Join的過程以下圖示。

SQL引擎從兩表的第一行開始匹配,發現左表的1值小於右表的2值,因此左表讀取下一條記錄繼續匹配,當左右兩表的值都爲2時,該記錄符合匹配條件,而後右表讀取下一條記錄繼續匹配,發現二者不等於而且左表值小於右表值後,左表讀取下一條繼續匹配,一直到t1或者t2表的數據所有讀區完畢,Merge Join纔算結束。

 

Merge Join若是不考慮排序的開銷,效率要比Hash Join要高,可是若是左右表都須要作複雜度O(n*)的排序,則關聯效率確定要比Hash Join要低。

Merge Join主要使用的場景爲

1) 關聯的字段在兩張表中都索引,能夠支持快速排序,或者須要關聯的表的關聯字段自己是有序的

2) 兩張數據量較大的表關聯,Merge Join的性能會比 NL Join性能要好

典型的SQL命令以下

select t1.name,t2.info

    from t1,t2

    where t1.id=t2.id order by t1.id , t2.id;

3 SequioaSQL介紹

SequoiaSQL是SequoiaDB的SQL引擎,爲用戶提供基於SQL語言訪問SequoiaDB的方法,可以大大下降用戶須要從新學習SequoiaDB驅動API的難度,繼續沿用JDBC驅動開發應用程序,同時也能利用成熟的GUI工具操做數據庫。

3.1 SequoiaDB支持SQL

SequoiaDB自己是一款分佈式文檔型數據庫,它爲用戶提供了各類開發語言的驅動程序,例如:Java、PHP、Python、C#、C++、C、Javascript等,可是這些驅動程序都只支持使用API方式操做數據庫。

可是用戶若是但願使用SQL語言對SequoiaDB作開發,也能夠選擇部署SequoiaSQL或者PostgreSQL來補充SequoiaDB的開發接口,這樣用戶就可使用標準的JDBC驅動開發程序代碼了。

3.2 SequoiaSQL支持的關聯策略

目前用戶能夠經過SequoiaSQL或者PostgreSQL來擴展SequoiaDB的開發接口,而且二者都支持2003 SQL標準。可是二者在底層的運行機制上仍是有所區別,最明顯一點就是Sequoia SQL支持NL Join和Hash Join兩種關聯策略,而以PostgreSQL作爲SequoiaDB的SQL引擎只可以支持Hash Join一種關聯策略。

4 SequoiaSQL 關聯查詢操做

4.1 SequoiaSQL 關聯策略說明

因爲SequoiaSQL在作關聯查詢時,實際上數據的提供者就是SequoiaDB,因此在不一樣的關聯策略生效時,對於SequoiaDB數據庫有不一樣的表現。

例如

1) 若是SequoiaSQL使用Hash Join策略執行關聯查詢,則SequoiaDB會表現出大量的數據讀,而索引讀則爲零;

2) 若是Sequoia SQL使用NL Join策略執行關聯查詢,則SequoiaDB會有較大的索引讀,而數據讀和索引讀的數值至關。

用戶能夠在sdb shell中執行如下快照命令查看

db.snapshot(SDB_SNAP_DATABASE)

快照結果中,TotalDataRead表明數據讀的數值,TotalIndexRead表明索引讀的數據,該數值始終保持遞增狀態,若是用戶想用更加簡單的方法瞭解當前數據庫平均每秒數據讀和索引讀的數值,可使用sdbtop工具進行查看。

4.2 NL join要求

SequoiaSQL的NL Join功能由引擎配置文件的enable_nestloop參數控制是否開啓,固然該功能默認是開啓的。

SequoiaSQL在作關聯查詢時須要執行NL Join關聯策略,須要知足如下條件

1) enable_nestloop參數設置爲on

2) 關聯右表(也叫探查表、內部表)的關聯字段有建立索引

3) 關聯左表(也叫驅動表、外部表)的數據量相對較少

4.3 Hash join要求

SequoiaSQL在執行關聯查詢時,若是不知足NL Join的要求,則自動選擇使用Hash Join完成關聯查詢。

4.4 查看關聯策略

用戶在SequoiaSQL的操做控制窗口中,能夠經過explain+SQL命令查看引擎的關聯策略,例如存在duebill和contract 兩張表,每張表中都存儲了2000萬記錄,而且兩表的關聯條件爲

duebill.relativeserialno2=contract.serialno

 

若是開始時只對duebill表中relativeserialno2 建立了索引,而contract表中 serialno 字段沒有索引,此時使用expalin查看訪問計劃,用戶將會看到引擎是使用Hash join完成關聯查詢。

 

此時使用Hash join的SQL查詢效率較低,須要18.9秒

 

而若是用戶對contract表中的serialno 字段建立索引後,再使用相同的SQL查看引擎的訪問計劃,將會變成NL join策略。

 

並且用戶能夠發現使用NL join 的查詢效率比使用Hash join的查詢效率高不少,關聯查詢只須要7毫秒。

5 總結

本篇文章主要向讀者介紹了數據庫在作關聯查詢時,數據庫底層的技術原理。做者結合SequoiaSQL自身的技術特性,向用戶介紹在什麼場景下應該使用哪一種關聯策略,以及若是用戶須要使用NL Join關聯策略,SequoiaDB數據庫應該知足什麼條件纔可以正確觸發SequoiaSQL的NL Join關聯查詢。

SequoiaDB是一款分佈式文檔型數據庫,自從在2013年發佈以後,受到愈來愈開發者的喜好和普遍的使用。SequoiaDB通過這些年的發展,功能覆蓋已經較爲全面,例如支持分佈式事務、完整對接大數據主流產品、異地災備、分佈式塊存儲等,而且SequoiaDB還爲開發者提供完整的SQL支持。

目前,SequoiaDB自研的SQL訪問組件SequoiaSQL做爲企業版的功能之一已經提供給上百家企業用戶使用,而且已經實現分佈式架構下的SQL 2003支持。

 

對於SequoiaDB社區版用戶,咱們能夠經過SequoiaDB對接PostgreSQL 實現社區版的分佈式SQL訪問。這一應用方式基本也能夠知足大部分的社區版需求。

相關文章
相關標籤/搜索