專利名稱:去除sql查詢語(yǔ)句恒條件的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及一種改寫(xiě)SQL查詢語(yǔ)句的方法,具體地說(shuō),是涉及一種利用鏈表來(lái)去除SQL查詢語(yǔ)句中存在的恒條件的方法。
背景技術(shù):
在日常應(yīng)用中,數(shù)據(jù)庫(kù)經(jīng)常需要處理大規(guī)模的數(shù)據(jù),查詢是用戶經(jīng)常使用的操作,一個(gè)復(fù)雜的查詢語(yǔ)句會(huì)使數(shù)據(jù)庫(kù)系統(tǒng)進(jìn)行大量繁瑣的數(shù)據(jù)處理,如WHERE條件的復(fù)雜度能很大地影響數(shù)據(jù)庫(kù)的查詢速度。
目前,公知的數(shù)據(jù)庫(kù)查詢優(yōu)化技術(shù)都不能在語(yǔ)義級(jí)別消去復(fù)雜的WHERE恒條件,這樣就導(dǎo)致了查詢執(zhí)行器在掃描表的每一行時(shí)都需要用WHERE條件進(jìn)行篩選,從而大大增加了數(shù)據(jù)處理開(kāi)銷。若查詢優(yōu)化器能從語(yǔ)義判斷上消去一些不必要的WHERE條件的話,執(zhí)行器便會(huì)顯著減少運(yùn)行時(shí)間,提高系統(tǒng)的整體性能,故如何去除SQL查詢語(yǔ)句中的恒條件是今后查詢優(yōu)化的關(guān)鍵。
發(fā)明內(nèi)容
本發(fā)明的目的是提供一種去除SQL查詢語(yǔ)句恒條件的方法,該方法根據(jù)查詢語(yǔ)句來(lái)創(chuàng)建鏈表、合并鏈表,可在語(yǔ)義級(jí)別上有效地消去SQL查詢語(yǔ)句的恒條件,顯著降低數(shù)據(jù)庫(kù)系統(tǒng)執(zhí)行器的處理開(kāi)銷。
為實(shí)現(xiàn)上述目的,本發(fā)明采用以下技術(shù)方案一種去除SQL查詢語(yǔ)句恒條件的方法,它包括以下步驟創(chuàng)建鏈表步驟首先將CHECK約束和WHERE條件都轉(zhuǎn)換成查詢樹(shù)的子樹(shù),其中,葉節(jié)點(diǎn)是CHECK約束和WHERE條件中的表達(dá)式節(jié)點(diǎn),其他的節(jié)點(diǎn)是AND或者OR節(jié)點(diǎn),然后對(duì)CHECK約束子樹(shù)和WHERE條件子樹(shù)進(jìn)行后序遍歷,遇到表達(dá)式節(jié)點(diǎn)則生成一個(gè)列屬性鏈表;合并鏈表步驟在進(jìn)行后序遍歷過(guò)程中,遇到AND或者OR節(jié)點(diǎn)則合并該節(jié)點(diǎn)的子樹(shù)的列屬性鏈表;改寫(xiě)查詢語(yǔ)句步驟在合并鏈表的過(guò)程中,若發(fā)現(xiàn)恒真或恒假條件,則將條件節(jié)點(diǎn)改寫(xiě)為TRUE或FALSE常量節(jié)點(diǎn),若最后該子樹(shù)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則去掉WHERE條件;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則將該SQL查詢直接改寫(xiě)為空查詢。
本發(fā)明的優(yōu)點(diǎn)是由于在語(yǔ)義級(jí)別上有效地消去了SQL查詢語(yǔ)句的恒條件,因而避免了無(wú)關(guān)緊要的查詢處理,顯著降低了數(shù)據(jù)庫(kù)系統(tǒng)執(zhí)行器對(duì)恒真恒假查詢條件的處理開(kāi)銷。
圖1是本發(fā)明方法流程簡(jiǎn)圖;圖2是CHECK約束和WHERE條件轉(zhuǎn)換后的樹(shù)結(jié)構(gòu)示意圖;圖3是結(jié)構(gòu)體的構(gòu)成示意圖;圖4是列屬性鏈表和區(qū)間鏈表示意圖;圖5是創(chuàng)建鏈表的流程圖;圖6是合并列屬性鏈表的流程圖;圖7是用AND邏輯合并區(qū)間鏈表的流程圖;圖8是用OR邏輯合并區(qū)間鏈表的流程圖;圖9是本發(fā)明的一個(gè)實(shí)施例示意圖;圖10是優(yōu)化查詢語(yǔ)句的一般流程。
具體實(shí)施例方式
在OSCAR數(shù)據(jù)庫(kù)中,parser語(yǔ)法解析子模塊將字符串形式的SQL查詢語(yǔ)句轉(zhuǎn)換成一個(gè)parse tree結(jié)構(gòu),然后analyze語(yǔ)義分析子模塊將parse tree結(jié)構(gòu)轉(zhuǎn)換成內(nèi)部識(shí)別的Query查詢樹(shù)結(jié)構(gòu),SQL語(yǔ)句的不同部分轉(zhuǎn)換成了查詢樹(shù)的各個(gè)子樹(shù),接下來(lái)Optimizer查詢優(yōu)化模塊對(duì)Query結(jié)構(gòu)進(jìn)行優(yōu)化,生成執(zhí)行計(jì)劃Plan,提交給Executer執(zhí)行器模塊執(zhí)行得到查詢結(jié)果。本發(fā)明位于Optimizer模塊中基于規(guī)則的優(yōu)化子模塊中。
本發(fā)明方法包括圖1所示的三個(gè)步驟創(chuàng)建鏈表、合并鏈表和改寫(xiě)查詢語(yǔ)句。
本發(fā)明首先將CHECK約束和WHERE條件都轉(zhuǎn)換成查詢樹(shù)的子樹(shù),表達(dá)式的樹(shù)結(jié)構(gòu)如圖2所示,葉節(jié)點(diǎn)是表達(dá)式節(jié)點(diǎn),如“列=1”、“列IS NOT NULL”等等,其他的節(jié)點(diǎn)是AND或者OR節(jié)點(diǎn)。本發(fā)明對(duì)這兩個(gè)子樹(shù)進(jìn)行后序遍歷,遇到表達(dá)式節(jié)點(diǎn)則生成一個(gè)列屬性鏈表,遇到AND或者OR節(jié)點(diǎn)則合并該節(jié)點(diǎn)的子樹(shù)的列屬性鏈表,在合并鏈表的過(guò)程中,若發(fā)現(xiàn)恒真或恒假條件,則將條件節(jié)點(diǎn)改寫(xiě)為TRUE或FALSE常量節(jié)點(diǎn)。若最后該子樹(shù)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則WHERE條件可以去掉;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則該SQL查詢可以直接改寫(xiě)為空查詢。
本發(fā)明對(duì)CHECK約束和WHERE條件的樹(shù)結(jié)構(gòu)進(jìn)行后序遍歷,遇到表達(dá)式節(jié)點(diǎn)就創(chuàng)建列屬性鏈表,遇到AND或OR節(jié)點(diǎn)就合并鏈表并改寫(xiě)查詢語(yǔ)句,這個(gè)遞歸的過(guò)程一直持續(xù)到遍歷完樹(shù)中每個(gè)節(jié)點(diǎn)。因?yàn)樵贑HECK約束和WHERE條件的樹(shù)結(jié)構(gòu)中,葉節(jié)點(diǎn)都是表達(dá)式節(jié)點(diǎn),其他的節(jié)點(diǎn)都是AND或OR節(jié)點(diǎn),因此采用后序遍歷能確保對(duì)于AND或OR連接的各個(gè)表達(dá)式,先分別生成它們的列屬性鏈表,再根據(jù)AND或OR語(yǔ)義合并成一個(gè)鏈表。
下面結(jié)合附圖對(duì)本發(fā)明方法作詳細(xì)說(shuō)明。
一.創(chuàng)建鏈表步驟本發(fā)明的第一步驟創(chuàng)建鏈表,是指遍歷CHECK約束和WHERE條件時(shí),對(duì)遇到的每個(gè)表達(dá)式創(chuàng)建結(jié)構(gòu)體ExprListNode,并由該結(jié)構(gòu)體生成一個(gè)單節(jié)點(diǎn)的列屬性鏈表。
如圖3所示,結(jié)構(gòu)體ExprListNode有四個(gè)域(1)col列名;(2)is_nullCHECK約束和WHERE條件中有沒(méi)有對(duì)該列的IS NULL約束;(3)is_not_nullCHECK約束和WHERE條件中有沒(méi)有對(duì)該列的IS NOT NULL約束;(4)exprFieldList列的區(qū)間鏈表,區(qū)間鏈表的每個(gè)節(jié)點(diǎn)為一ExprField結(jié)構(gòu)體,每個(gè)節(jié)點(diǎn)表示該列在CHECK約束和WHERE條件語(yǔ)句中出現(xiàn)的一個(gè)區(qū)間,節(jié)點(diǎn)間的關(guān)系體現(xiàn)為區(qū)間之間的OR連接。結(jié)構(gòu)體ExprField也有四個(gè)域(1)minnum區(qū)間的左邊界;(2)maxnum區(qū)間的右邊界(3)left_is_close左邊界是否為閉區(qū)間;(4)right_is_close右邊界是否為閉區(qū)間。
依照上述結(jié)構(gòu)體ExprListNode和結(jié)構(gòu)體ExprField的定義,對(duì)CHECK約束和WHERE條件語(yǔ)句中出現(xiàn)的每個(gè)表達(dá)式分別創(chuàng)建結(jié)構(gòu)體ExprListNode和結(jié)構(gòu)體ExprField,然后將結(jié)構(gòu)體ExprField鏈接到結(jié)構(gòu)體ExprListNode的exprFieldList域中,如圖4所示的若干列屬性鏈表和區(qū)間鏈表實(shí)例,區(qū)間鏈表是列屬性鏈表的exprFieldList域中所掛的鏈表。
創(chuàng)建鏈表的具體流程如圖5所示,包括步驟1、創(chuàng)建結(jié)構(gòu)體ExprListNode,is_null和is_not_null域賦初值為FALSE,exprFieldList域賦初值為空鏈表。將表達(dá)式中的列提取出來(lái)賦值給ExprListNode的col域。
2、如果表達(dá)式是IS NULL或者IS NOT NULL約束,則將ExprListNode結(jié)構(gòu)體中對(duì)應(yīng)的域賦值為TRUE,轉(zhuǎn)到5。
3、如果表達(dá)式是(列 操作符 常數(shù)),則創(chuàng)建ExprField結(jié)構(gòu)體ExprField1,ExprField1的minnum和maxnum域賦初值為空指針NULL,left_is_close和right_is_close域賦初值為FALSE。
4、判斷表達(dá)式的操作符(a)若是列=常數(shù)con,表示為區(qū)間[con,con],則ExprField1各個(gè)域賦值為(con,con,TRUE,TRUE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;(b)若是列<常數(shù)con,表示為區(qū)間(-∞,con),則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;(c)若是列<=常數(shù)con,表示為區(qū)間(-∞,con],則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,TRUE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;(d)若是列>常數(shù)con,表示為區(qū)間(con,+∞),則ExprField1各個(gè)域賦值為(con,NULL,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;(e)若是列>=常數(shù)con,表示為區(qū)間[con,+∞),則ExprField1各個(gè)域賦值為(con,NULL,TRUE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;(f)若是列<>常數(shù)con,表示為區(qū)間(-∞,con)∪(con,+∞),則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,F(xiàn)ALSE),創(chuàng)建ExprField結(jié)構(gòu)體ExprField2,各個(gè)域賦值為(con,NULL,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1和ExprField2生成兩個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到5;5、返回用ExprListNode生成的單個(gè)節(jié)點(diǎn)的鏈表,結(jié)束。
二.合并鏈表步驟本發(fā)明的第二步驟合并鏈表是指遍歷CHECK約束和WHERE條件時(shí),對(duì)遇到的每個(gè)AND或OR節(jié)點(diǎn),將該節(jié)點(diǎn)的所有子樹(shù)的列屬性鏈表合并成一個(gè)鏈表,合并后的新鏈表是按照列序號(hào)進(jìn)行排序的。合并列屬性鏈表的具體流程如圖6所示,包括步驟1、如果兩鏈表都為空,返回空鏈表;2、如果一個(gè)鏈表為空,若操作符為AND則返回空鏈表;若操作符為OR則返回另一個(gè)非空的鏈表;3、對(duì)兩個(gè)鏈表,依次將序號(hào)小的列的節(jié)點(diǎn)連接到新鏈表后面,并將這個(gè)鏈表的指針后移一位,如果兩列是同一列,則合并兩個(gè)ExprListNode節(jié)點(diǎn)的exprFieldList域,即先合并兩列的列屬性鏈表后再連接到新鏈表后面;4、如果有一個(gè)鏈表的指針為空了,則將另一個(gè)鏈表的剩余部分連接到新鏈表后面,返回新鏈表。
其中,步驟3中的合并兩相同列的區(qū)間鏈表,對(duì)于AND連接的表達(dá)式生成的列屬性鏈表和OR連接的表達(dá)式生成的列屬性鏈表,實(shí)現(xiàn)合并的方法是不同的。我們用窮舉法列出用AND和OR連接各種類型的表達(dá)式生成的區(qū)間鏈表的規(guī)則ExprListNode結(jié)構(gòu)的節(jié)點(diǎn)簡(jiǎn)單記為(is_null,is_not_null,exprFieldList)。is_null和is_not_null可以取值TRUE和FALSE,分別表示col IS NULL和col IS NOTNULL,exprFieldList可以取值為空鏈表和非空鏈表,表示除了col IS NULL和col IS NOT NULL之外的其他表達(dá)式,如col>1。
(1)is_null和is_not_null不能同時(shí)為TRUE,因?yàn)殒湵砗喜r(shí)會(huì)判斷為恒假條件而消去;(2)ExprListNode結(jié)構(gòu)的節(jié)點(diǎn)不會(huì)是(FALSE,TRUE,非空鏈表),例如(a)col>1 and col IS NOT NULL,鏈表合并成了col>1;(b)col>1 or col IS NOTNULL,鏈表合并成了col IS NOT NULL。
(3)ExprListNode結(jié)構(gòu)的節(jié)點(diǎn)不會(huì)是(FALSE,F(xiàn)ALSE,空鏈表),因?yàn)椴缓魏伪磉_(dá)式的空指針不會(huì)建立區(qū)間鏈表。
因此ExprListNode結(jié)構(gòu)的節(jié)點(diǎn)只有四種狀態(tài),分別為狀態(tài)1(TRUE,F(xiàn)ALSE,空鏈表),表示col IS NULL狀態(tài)2(TRUE,F(xiàn)ALSE,非空鏈表),表示col IS NULL or其他表達(dá)式狀態(tài)3(FALSE,TRUE,空鏈表),表示col IS NOT NULL狀態(tài)4(FALSE,F(xiàn)ALSE,非空鏈表),表示其他表達(dá)式用AND合并表達(dá)式的列屬性鏈表的規(guī)則見(jiàn)表1
表1用OR合并的表達(dá)式的列屬性鏈表的規(guī)則見(jiàn)表2
表2如圖7所示,用AND邏輯實(shí)現(xiàn)合并兩相同列的區(qū)間鏈表的過(guò)程為1、若兩個(gè)鏈表中有空鏈表,則把另一個(gè)鏈表連接到新鏈表后,返回新鏈表;2、兩個(gè)指針?biāo)傅墓?jié)點(diǎn)表示的區(qū)間有交集,則將交集連接到新鏈表后;3、如果鏈表1的指針?biāo)腹?jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)與鏈表2的指針?biāo)腹?jié)點(diǎn)有交集,則鏈表1的指針后移;如果鏈表2的指針?biāo)腹?jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)與鏈表1的指針?biāo)腹?jié)點(diǎn)有交集,則鏈表2的指針后移;否則兩個(gè)指針都后移(這個(gè)步驟也可以直接寫(xiě)為兩個(gè)指針都后移,這樣做是為了提高運(yùn)行效率);4、轉(zhuǎn)到1。
用OR邏輯實(shí)現(xiàn)合并兩相同列的區(qū)間鏈表的過(guò)程為1、如圖8-a所示,將兩個(gè)區(qū)間鏈表的節(jié)點(diǎn)依次插入到新鏈表中,確保新鏈表的節(jié)點(diǎn)按minnum遞增排序,過(guò)程為。
(1)若兩個(gè)鏈表中有空鏈表,則把另一個(gè)鏈表連接到新鏈表后,步驟1完,轉(zhuǎn)步驟2;(2)將兩個(gè)鏈表的指針?biāo)傅墓?jié)點(diǎn)中minnum較小的那個(gè)節(jié)點(diǎn)連接到新鏈表后,并且指針后移;若兩個(gè)鏈表的指針?biāo)傅墓?jié)點(diǎn)中minnum相等,則左邊為閉區(qū)間的節(jié)點(diǎn)先連接到新鏈表,然后連接另一個(gè),兩個(gè)指針都后移;(3)重復(fù)(1)~(2)。
2、如圖8-b所示,合并新鏈表中有交集的節(jié)點(diǎn)過(guò)程為依次取出新鏈表中的ExprField結(jié)構(gòu)的節(jié)點(diǎn),若相鄰的兩個(gè)節(jié)點(diǎn)表示的區(qū)間有交集,則將它們的交集保存到前一個(gè)節(jié)點(diǎn),從鏈表中刪掉后一個(gè)節(jié)點(diǎn)。
3、返回新鏈表。
三.改寫(xiě)查詢語(yǔ)句步驟本發(fā)明的第三步改寫(xiě)查詢語(yǔ)句,是指在第二步合并鏈表的過(guò)程中,若發(fā)現(xiàn)恒真或恒假條件,則將條件節(jié)點(diǎn)改寫(xiě)為TRUE或FALSE常量節(jié)點(diǎn);若AND節(jié)點(diǎn)的兒子節(jié)點(diǎn)存在FALSE常量,則將AND子樹(shù)改寫(xiě)為FALSE常量節(jié)點(diǎn);若AND節(jié)點(diǎn)的所有兒子節(jié)點(diǎn)都是TRUE常量,則將AND子樹(shù)改寫(xiě)為TRUE常量節(jié)點(diǎn);若OR節(jié)點(diǎn)的兒子節(jié)點(diǎn)存在TRUE常量,則將OR子樹(shù)改寫(xiě)為TRUE常量節(jié)點(diǎn);若OE節(jié)點(diǎn)的所有兒子節(jié)點(diǎn)都是FALSE常量,則將OR子樹(shù)改寫(xiě)為FALSE常量節(jié)點(diǎn);若發(fā)現(xiàn)幾個(gè)條件表達(dá)式可以合并,則將合并后的條件表達(dá)式節(jié)點(diǎn)取代原來(lái)的子樹(shù);若最后WHERE條件的樹(shù)結(jié)構(gòu)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則WHERE條件可以去掉;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則該SQL查詢可以直接改寫(xiě)為空查詢。
圖9所示為本發(fā)明的一個(gè)實(shí)施例示意圖,說(shuō)明如下例如表T1(TC1 int,TC2 int,TC3 int)上有約束tc1=1。
考慮SQL查詢SELECT * FROM T1 WHERE(TC1<1 OR TC1>1)AND TC2>3;1、如圖9-a所示,CHECK約束和WHERE條件轉(zhuǎn)換成了樹(shù)結(jié)構(gòu)。
2、后序遍歷CHECK約束的樹(shù)結(jié)構(gòu),只有一個(gè)表達(dá)式節(jié)點(diǎn)TC1=1,生成如圖4-c所示的列屬性鏈表。
3、后序遍歷WHERE條件的樹(shù)結(jié)構(gòu),先遇到表達(dá)式節(jié)點(diǎn)TC1<1,生成如圖4-e所示的列屬性鏈表,遇到表達(dá)式節(jié)點(diǎn)TC1>1,生成如圖4-d所示的列屬性鏈表,然后遇到OR節(jié)點(diǎn),對(duì)這兩個(gè)列屬性鏈表用OR合并,得到如圖9-b所示的列屬性鏈表。然后遇到表達(dá)式節(jié)點(diǎn)TC2>3,生成如圖9-c所示的列屬性鏈表。遍歷最后遇到AND節(jié)點(diǎn),將圖9-b和圖9-c所示的列屬性鏈表用AND合并,得到如圖9-d所示的列屬性鏈表。
4、合并CHECK約束和WHERE條件的列屬性鏈表,即用AND合并圖4-c和7-d所示的列屬性鏈表,兩個(gè)列屬性鏈表的TC1列的區(qū)間鏈表用AND合并時(shí),發(fā)現(xiàn)它們沒(méi)有交集,TC1的取值空間是空集,這是一個(gè)恒假條件,將WHERE條件的樹(shù)結(jié)構(gòu)的根節(jié)點(diǎn)改寫(xiě)為FALSE,因此SQL查詢語(yǔ)句改寫(xiě)成了SELECT * FROM T1WHERE FALSE。
5、將含有WHERE FALSE的這種恒假查詢直接改寫(xiě)為空查詢SELECT NULL;在神舟OSCAR關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)中,系統(tǒng)使用了兩種查詢優(yōu)化器,一種為基于規(guī)則的代數(shù)優(yōu)化器,另一種為基于代價(jià)的優(yōu)化器。其中,基于規(guī)則的代數(shù)優(yōu)化器使用了本發(fā)明的優(yōu)化方法,具體優(yōu)化流程如圖10所示對(duì)于基于規(guī)則的代數(shù)優(yōu)化器接收的每一條SQL查詢語(yǔ)句,規(guī)則適配器為之選擇合適的規(guī)則進(jìn)行優(yōu)化,如果該查詢語(yǔ)句匹配恒條件消去規(guī)則的觸發(fā)條件,則使用該規(guī)則處理查詢語(yǔ)句,否則使用其他匹配的規(guī)則處理該查詢語(yǔ)句。用某個(gè)規(guī)則優(yōu)化后的查詢語(yǔ)句還可以繼續(xù)用其他的規(guī)則對(duì)其進(jìn)行優(yōu)化,當(dāng)該查詢語(yǔ)句不能觸發(fā)規(guī)則庫(kù)中任意一個(gè)規(guī)則時(shí),規(guī)則迭代器將優(yōu)化后的查詢語(yǔ)句輸出給下一個(gè)模塊。
權(quán)利要求
1.一種去除SQL查詢語(yǔ)句恒條件的方法,其特征在于它包括步驟創(chuàng)建鏈表步驟首先將CHECK約束和WHERE條件都轉(zhuǎn)換成查詢樹(shù)的子樹(shù),其中,葉節(jié)點(diǎn)是CHECK約束和WHERE條件中的表達(dá)式節(jié)點(diǎn),其他的節(jié)點(diǎn)是AND或者OR節(jié)點(diǎn),然后對(duì)CHECK約束子樹(shù)和WHERE條件子樹(shù)進(jìn)行后序遍歷,遇到表達(dá)式節(jié)點(diǎn)則生成一個(gè)列屬性鏈表;合并鏈表步驟在進(jìn)行后序遍歷過(guò)程中,遇到AND或者OR節(jié)點(diǎn)則合并該節(jié)點(diǎn)的子樹(shù)的列屬性鏈表;改寫(xiě)查詢語(yǔ)句步驟在合并鏈表的過(guò)程中,若發(fā)現(xiàn)恒真或恒假條件,則將條件節(jié)點(diǎn)改寫(xiě)為TRUE或FALSE常量節(jié)點(diǎn),若最后該子樹(shù)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則去掉WHERE條件;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則將該SQL查詢直接改寫(xiě)為空查詢。
2.根據(jù)權(quán)利要求1所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于在所述創(chuàng)建鏈表步驟中,遍歷CHECK約束和WHERE條件時(shí),對(duì)遇到的每個(gè)表達(dá)式節(jié)點(diǎn)創(chuàng)建一結(jié)構(gòu)體ExprListNode,并由該結(jié)構(gòu)體生成一個(gè)單節(jié)點(diǎn)的列屬性鏈表。
3.根據(jù)權(quán)利要求2所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于所述結(jié)構(gòu)體ExprListNode有四個(gè)域(1)col列名;(2)is_nullCHECK約束和WHERE條件中有沒(méi)有對(duì)該列的IS NULL約束;(3)is_not_nullCHECK約束和WHERE條件中有沒(méi)有對(duì)該列的IS NOT NULL約束;(4)exprFieldList列的區(qū)間鏈表,區(qū)間鏈表的每個(gè)節(jié)點(diǎn)為一ExprField結(jié)構(gòu)體,每個(gè)節(jié)點(diǎn)表示該列在CHECK約束和WHERE條件語(yǔ)句中出現(xiàn)的一個(gè)區(qū)間,節(jié)點(diǎn)間的關(guān)系體現(xiàn)為區(qū)間之間的OR連接,該結(jié)構(gòu)體ExprField也有四個(gè)域(1)minnum區(qū)間的左邊界;(2)maxnum區(qū)間的右邊界;(3)left_is_close左邊界是否為閉區(qū)間;(4)right_is_close右邊界是否為閉區(qū)間。
4.根據(jù)權(quán)利要求3所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于所述創(chuàng)建鏈表的步驟是步驟(1)創(chuàng)建結(jié)構(gòu)體ExprListNode,對(duì)is_null和is_not_null域賦初值FALSE,exprFieldList域賦初值為空鏈表,將表達(dá)式中的列提取出來(lái)賦值給col域;步驟(2)如果表達(dá)式是IS NULL或者IS NOT NULL約束,則將ExprListNode結(jié)構(gòu)體中對(duì)應(yīng)的域賦值為TRUE,轉(zhuǎn)到步驟(5);步驟(3)如果表達(dá)式是列+操作符+常數(shù),則創(chuàng)建ExprField結(jié)構(gòu)體ExprField1,ExprField1的minnum和maxnum域賦初值為空指針NULL,left_is_close和right_is_close域賦初值為FALSE;步驟(4)判斷表達(dá)式的操作符(a)若是列=常數(shù)con,表示為區(qū)間[con,con],則ExprField1各個(gè)域賦值為(con,con,TRUE,TRUE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);(b)若是列<常數(shù)con,表示為區(qū)間(-∞,con),則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);(c)若是列<=常數(shù)con,表示為區(qū)間(-∞,con],則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,TRUE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);(d)若是列>常數(shù)con,表示為區(qū)間(con,+∞),則ExprField1各個(gè)域賦值為(con,NULL,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);(e)若是列>=常數(shù)con,表示為區(qū)間[con,+∞),則ExprField1各個(gè)域賦值為(con,NULL,TRUE,F(xiàn)ALSE),用ExprField1生成單個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);(f)若是列<>常數(shù)con,表示為區(qū)間(-∞,con)∪(con,+∞),則ExprField1各個(gè)域賦值為(NULL,con,F(xiàn)ALSE,F(xiàn)ALSE),創(chuàng)建ExprField結(jié)構(gòu)體ExprField2,各個(gè)域賦值為(con,NULL,F(xiàn)ALSE,F(xiàn)ALSE),用ExprField1和ExprField2生成兩個(gè)節(jié)點(diǎn)的鏈表,賦值給ExprListNode結(jié)構(gòu)體的exprFieldList域,轉(zhuǎn)到步驟(5);步驟(5)返回用ExprListNode生成的單個(gè)節(jié)點(diǎn)的鏈表,結(jié)束。
5.根據(jù)權(quán)利要求3所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于所述合并列屬性鏈表的過(guò)程是(1)如果兩鏈表都為空,返回空鏈表;(2)如果一個(gè)鏈表為空,若操作符為AND,則返回空鏈表,若操作符為OR,則返回另一個(gè)非空的鏈表;(3)對(duì)兩個(gè)鏈表,依次將序號(hào)小的列的節(jié)點(diǎn)連接到新鏈表后面,并將這個(gè)鏈表的指針后移一位,如果兩列是同一列,則合并兩個(gè)ExprListNode節(jié)點(diǎn)的exprFieldList域,即先合并兩列的列屬性鏈表后再連接到新鏈表后面;(4)如果有一個(gè)鏈表的指針為空,則將另一個(gè)鏈表的剩余部分連接到新鏈表后面,返回新鏈表。
6.根據(jù)權(quán)利要求5所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于當(dāng)合并兩相同列的區(qū)間鏈表時(shí)若是用AND邏輯實(shí)現(xiàn)合并,則合并過(guò)程為(1)若兩個(gè)鏈表中有空鏈表,則把另一個(gè)鏈表連接到新鏈表后,返回新鏈表;(2)若兩個(gè)指針?biāo)傅墓?jié)點(diǎn)表示的區(qū)間有交集,則將交集連接到新鏈表后;(3)如果鏈表1的指針?biāo)腹?jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)與鏈表2的指針?biāo)腹?jié)點(diǎn)有交集,則鏈表1的指針后移;如果鏈表2的指針?biāo)腹?jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)與鏈表1的指針?biāo)腹?jié)點(diǎn)有交集,則鏈表2的指針后移;否則兩個(gè)指針都后移;(4)轉(zhuǎn)到(1),若是用OR邏輯實(shí)現(xiàn)合并,則合并過(guò)程為(5)將兩個(gè)區(qū)間鏈表的節(jié)點(diǎn)依次插入到新鏈表中,確保新鏈表的節(jié)點(diǎn)按minnum遞增排序,其中。(5.1)若兩個(gè)鏈表中有空鏈表,則把另一個(gè)鏈表連接到新鏈表后,轉(zhuǎn)(6),否則繼續(xù)(5.2);(5.2)將兩個(gè)鏈表的指針?biāo)傅墓?jié)點(diǎn)中minnum較小的那個(gè)節(jié)點(diǎn)連接到新鏈表后,并且指針后移;若兩個(gè)鏈表的指針?biāo)傅墓?jié)點(diǎn)中minnum相等,則左邊為閉區(qū)間的節(jié)點(diǎn)先連接到新鏈表,然后連接另一個(gè),兩個(gè)指針都后移;(5.3)重復(fù)(5.1)~(5.2);(6)合并新鏈表中有交集的節(jié)點(diǎn)過(guò)程為依次取出新鏈表中的ExprField結(jié)構(gòu)的節(jié)點(diǎn),若相鄰的兩個(gè)節(jié)點(diǎn)表示的區(qū)間有交集,則將它們的交集保存到前一個(gè)節(jié)點(diǎn),從鏈表中刪掉后一個(gè)節(jié)點(diǎn);(7)返回新鏈表。
7.根據(jù)權(quán)利要求1所述的去除SQL查詢語(yǔ)句恒條件的方法,其特征在于在所述改寫(xiě)查詢語(yǔ)句步驟中若AND節(jié)點(diǎn)的兒子節(jié)點(diǎn)存在FALSE常量,則將AND子樹(shù)改寫(xiě)為FALSE常量節(jié)點(diǎn);若AND節(jié)點(diǎn)的所有兒子節(jié)點(diǎn)都是TRUE常量,則將AND子樹(shù)改寫(xiě)為TRUE常量節(jié)點(diǎn),若OR節(jié)點(diǎn)的兒子節(jié)點(diǎn)存在TRUE常量,則將OR子樹(shù)改寫(xiě)為TRUE常量節(jié)點(diǎn);若OR節(jié)點(diǎn)的所有兒子節(jié)點(diǎn)都是FALSE常量,則將OR子樹(shù)改寫(xiě)為FALSE常量節(jié)點(diǎn);若發(fā)現(xiàn)幾個(gè)條件表達(dá)式可以合并,則將合并后的條件表達(dá)式節(jié)點(diǎn)取代原來(lái)的子樹(shù);若最后WHERE條件的樹(shù)結(jié)構(gòu)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則去掉WHERE條件;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則該SQL查詢直接改寫(xiě)為空查詢。
全文摘要
本發(fā)明是一種去除SQL查詢語(yǔ)句恒條件的方法,包括創(chuàng)建鏈表、合并鏈表和改寫(xiě)查詢語(yǔ)句三個(gè)步驟。它將CHECK約束和WHERE條件都轉(zhuǎn)換成查詢樹(shù)的子樹(shù),葉節(jié)點(diǎn)是表達(dá)式節(jié)點(diǎn),其他的節(jié)點(diǎn)是AND或者OR節(jié)點(diǎn),對(duì)這兩個(gè)子樹(shù)進(jìn)行后序遍歷,遇到表達(dá)式節(jié)點(diǎn)則生成一個(gè)列屬性鏈表,遇到AND或者OR節(jié)點(diǎn)則合并該節(jié)點(diǎn)的子樹(shù)的列屬性鏈表,在合并鏈表的過(guò)程中,若發(fā)現(xiàn)恒真或恒假條件,則將條件節(jié)點(diǎn)改寫(xiě)為TRUE或FALSE常量節(jié)點(diǎn),若最后該子樹(shù)的根節(jié)點(diǎn)被改寫(xiě)為TRUE,則WHERE條件可以去掉;若根節(jié)點(diǎn)被改寫(xiě)為FALSE,則該SQL查詢可以直接改寫(xiě)為空查詢。由于本發(fā)明在語(yǔ)義級(jí)別上有效地消去了SQL查詢語(yǔ)句的恒條件,因而避免了無(wú)關(guān)緊要的查詢處理,顯著降低了數(shù)據(jù)庫(kù)系統(tǒng)執(zhí)行器對(duì)恒真恒假查詢條件的處理開(kāi)銷。
文檔編號(hào)G06F17/30GK101075255SQ200710100359
公開(kāi)日2007年11月21日 申請(qǐng)日期2007年6月8日 優(yōu)先權(quán)日2007年6月8日
發(fā)明者郭毅 申請(qǐng)人:北京神舟航天軟件技術(shù)有限公司