JOIN是關係數據庫中經常使用運算,用於把多個表進行關聯,關聯條件通常是判斷某個關聯字段的值是否相等。隨着關聯表的增多或者關聯條件愈來愈複雜,不管理解查詢含義、實現查詢語句,仍是在查詢的性能方面,能夠說JOIN都是最具挑戰的SQL運算,沒有之一。算法
特別是JOIN的性能,一直是個老大難問題。下面咱們將基於數據計算中間件(DCM)——集算器,來提供一些提高運算性能的方法。數據庫
固然,咱們不是介紹如何在寫SQL語句時怎麼寫JOIN,也就是咱們假設已經對查詢需求有了正確的理解而且能正確地實現SQL。這種狀況下,要提高性能,就必須從最基本的提高數據IO配合算法及並行等手段作起。正因如此,若是數據仍然存儲在數據庫中,那也沒什麼好辦法提速,由於數據庫的IO效率很低,又幾乎沒法並行,即便把運算寫得再精巧也無濟於事。因此,要提升性能,必定要把數據搬出數據庫,咱們下面的討論都是基於這個思路,而集算器正是實現這個思路的利器,甚至神器!性能
把數據表搬出數據庫存儲到集算器的集文件中很簡單,只要用兩行代碼:優化
Aspa |
|
1指針 |
=db.cursor("select * from 訂單表")中間件 |
2對象 |
=file("Order.btx").export@b(A1)get |
這兩行代碼把數據庫裏訂單表的數據導出到集文件Order.btx。產品
由於數據庫IO性能不佳,並且數據量也可能很大,因此這個「搬家」動做可能時間也不短,但還好是一次性的。後面咱們的計算都將從集文件中取數。
在將數據搬出數據庫後,咱們須要首先判斷JOIN的類型,而後才能採起有針對性的優化措施。
JOIN運算你們都很熟悉,按照SQL的語法定義劃分,包括INNER JOIN(內鏈接)、LEFT JOIN(左鏈接)、RIGHT JOIN(右鏈接)、FULL JOIN(全鏈接)幾個類型,這是根據在運算中對空值的處理規則進行劃分的。而咱們的分析和優化,則會從更貼近需求的語義角度出發,根據各個表的主鍵參與關聯的狀況進行劃分,整體來講有這麼三種:外鍵表、同維表、主子表。
外鍵表
當表A的某些字段與表B的主鍵關聯,B稱爲A的外鍵表,A表中與B表主鍵關聯的字段稱爲A指向B的外鍵。此時A表也稱爲事實表,B表也稱爲維表。
表A:Order訂單表 |
|
ID |
訂單編號 |
CustomerID |
客戶編號 |
SellerID |
銷售編號 |
OrderDate |
訂購日期 |
Amount |
訂單金額 |
表B:Customer客戶表 |
|
ID |
客戶編號 |
Name |
客戶名稱 |
Area |
所在區域 |
表C:seller銷售人員表 |
|
ID |
員工編號 |
Name |
姓名 |
Age |
年齡 |
…… |
這是一個典型的例子,訂單表的客戶編號與客戶表的主鍵客戶編號進行關聯,此時A指向B是多對一的關係,即A表有可能存在多條記錄指向B表的同一條記錄。
這種狀況,咱們能夠把外鍵字段(例子中的「CustomerID」)的值理解成指向外鍵表中對應記錄的「指針」,而外鍵表中對應的記錄就能夠理解成一個對象,而外鍵表的字段就能夠理解爲對象的屬性, 「指針」的做用只是用於找到外鍵表中對應那條記錄。例子中對錶A和表B作關聯,必定是想得到某些訂單的客戶的姓名或所在區域等詳細信息,這樣,若是能寫成customerID.name和customerID.area就會更容易理解,這種語法在集算器中也獲得了完美的支持。
同時,表A還能夠有多個外鍵表,例如表A的銷售編號(SellerID)能夠指向一個銷售人員信息表C,從而得到該訂單銷售人員的屬性信息。
同維表
表A的主鍵與表B的主鍵關聯,A和B相互稱爲同維表。同維表是一對一的關係,JOIN、LEFT JOIN和FULL JOIN的狀況都會有,例如:員工表和經理表。
表A:employee員工表 |
|
ID |
員工編號 |
Name |
姓名 |
Salary |
工資 |
表B:manager客戶表 |
|
ID |
編號 |
Allowance |
補貼 |
…… |
這兩個表的主鍵都是員工編號ID,也就是經理也是員工之一,不過由於經理比普通員工多了一些屬性,因此須要另用一個經理表來保存。對於這種一對一的狀況,邏輯上能夠簡單地當作一個表來對待。同維表JOIN時兩個表都是按主鍵關聯,相應記錄是惟一對應的。
主子表
表A的主鍵與表B的部分主鍵關聯,A稱爲主表,B稱爲子表。主子表是一對多的關係,只有JOIN和LEFT JOIN,不會有FULL JOIN,如:訂單和訂單明細。
表A:Order訂單表 |
|
ID |
訂單編號 |
CustomerID |
客戶編號 |
OrderDate |
訂購日期 |
…… |
表B:OrderDetail訂單明細表 |
|
ID |
訂單編號 |
NO |
訂單序號 |
Product |
訂購產品 |
Price |
價格 |
…… |
表A的主鍵是ID,表B的主鍵是ID和NO,表A裏的一條記錄會對應表B裏的多條記錄。此時,能夠把訂單明細表裏的相關記錄當作是訂單表的一條記錄的屬性,該屬性的取值是一個集合,並且經常須要使用聚合運算把集合值計算成單值。例如查詢每一個訂單的總金額,能夠描述爲:
SELECT ID, SUM(OrderDetail.Price) FROM Order
顯然,主子表關係是不對等的,並且從兩個方向的引用都有意義。從主表引用子表的狀況就是經過聚合運算獲得一個單值,而從子表引用主表則和外鍵表相似。
那麼,這樣劃分三種JOIN運算,外鍵表、同維表、主子表,有什麼用處呢?固然是爲了優化性能!對於須要優化的JOIN運算,在準確判斷是哪一種類型基礎上,後面的優化纔會更加有效。另外,有必要說明一下,這裏提到的表A和表B不要求必須是一個實體表,也多是一個子查詢產生的「邏輯表」。
下面咱們就開始針對這三種類型以及實際的業務狀況進行分析和提速。
詳情能夠瀏覽原文地址