Unnesting Arbitrary Queries - T Neumann, A Kemper
The Complete Story of Joins (in HyPer) - Thomas Neumann, Viktor Leis, Alfons Kempersql
如其名,這篇paper講的就是如何unnestingapp
看個簡單的例子,這裏稱相關子查詢爲,dependent join3d
通過unnesting後獲得下面的SQLblog
能夠看到,unnesting的過程就是,把where中的標量子查詢,放到from中成爲一個derived tableit
全部的unnesting的思路,基本都是如此,把依賴外部的參數提出,剩下獨立的sql生成臨時derived table,而後再和外部的表進行joinio
先給出inner join 的定義,table
inner join就是對笛卡爾積,cross product,的一個selectionfunction
接着定義,dependent join,select
從公式中看出,T2是個function,t2是T2(t1)的輸出結果,同時結果還須要知足selection p
這裏叫join有些confuse,微軟定義爲apply算子跟容易理解些im
這裏以TPCH-21爲例子,
這裏把selection上提,消除了l2的參數,轉化爲regular join
爲何把selection上提是合理的?
有selection的時候,對知足的條件的row執行sql,因此把selection上提後,就是對全量row執行sql
獲得的結果是原來的超集
而後在外層再經過selection過濾,效果上是等價的
上面只是一個例子,那麼對於general的場景下,如何進行unnesting?
首先作一步轉換,
D是個T1的子集,僅僅包含T2所須要的參數列的distinct
這樣作的好處是,D是一個遠小於T1的表,尤爲若是T1的參數列有大量的重複的話
T2原先須要對T1的每一行都apply,可是如今只須要對distinct後的行
因此這裏就把一個dependent join,轉化成一個nicer的dependent join和一個regular join
以這個sql爲例,
能夠看出這個轉換是等價的
再者,須要消除Dependent Join
消除的條件以下,
當D的輸出列和T的參數列不相交的時候,就能夠轉化爲regular join
若是不知足的,就須要用下面的公式去轉換,
Selection
前面已經解釋了,爲何selection上提是合理的
Join
對於inner join,自己是有交換和結合率的,因此能夠簡單的把和D沒有依賴的join先提出
若是兩邊都依賴D的話,須要將D複製一份,分別和兩個進行Dependent Join
一樣對於Outer Join和Semi Join這種不支持交換率的狀況,也須要複製D
GroupBY
GroupBy在上提後,會須要加上join key
根據這些規則,消除的過程以下,
上提GroupBy,按照規則,上提後, group by的column加上d.id
上提selection
此時,dependent join的左右已經不相干,
因此將dependent join轉換爲regular join
把selection下推到join上
主要介紹兩種特殊的Join算子,
對於下面的Sql,
子查詢若是返回不止一條結果,須要報錯
這就是須要加上Max1Row
而SingleJoin把Max1Row集成到算子內部,
看下這條Sql,
子查詢後面有個or,Disjunction predicates
這樣若是直接轉成semi-join會有問題,由於那些可能知足or Sabbatical = true的行在join的時候會被篩選掉,上面拿不到
因此一個天然的想法就是,咱們在join的時候不去篩選數據,把數據都保留下來,只是給每行打標,true,false,null
能夠看到Mark Join的定義,多出一個m,用於標記是否知足join條件
由於Mark join沒有篩選行,因此在最外層,咱們能夠自由的經過projection來挑選數據,
這裏會選m爲true,或者Sabbatical=true的行
MarkJoin在對null值的處理上也會很方便