精華推薦 加速SQL查詢的特徵函式法

2021-04-17 05:58:18 字數 3863 閱讀 6214

1. 查詢問題的挑戰

關聯式資料庫的查詢優化始終是乙個重要而實際的問題,在那些以查詢為主的應用系統中,這幾乎是乙個成敗攸關的問題。但迄今為止,關於這個問題的討論中所提出的種種解決方案大致可分為兩大類,即利用硬體體系結構上的優勢及dbms對並行處理的支援能力的一類方案及完全由應用設計來處理的方案。在本文作者以前所發表的文章中曾推薦過利用臨時中介表和表更新方法和快查詢處理的策略。在同一篇文章中,我們也曾提到有可能利用程式變換支援查詢優化的想法。所有這些建議和想法都屬於應用設計類的處理辦法,這些方法從某種意義上說有一定的一般性。但是,實際應用不斷地提出這樣或那樣難而「怪」的問題,這些問題極富挑戰性,用常規方法往往要以很昂貴的系統資源為代價才有望解決。

本文的目的是向讀者介紹一種由e.birger等人首先提出的方法,即加速

查詢處理的特徵函式法。這個方法適用於大多數sql的資料庫系統,如果這類系統還包括為數不多的幾個(最少為2個)內部函式,如abs()及sign()等,則這個方法就是直接可用的了。在e.birger等人關於這個方法的研究報告中,曾給出很多極有難度而又很典型的查詢要求及其求解辦法,其中包括分技條件查詢、求行內量的邊界值、求直方圖、表轉置、求中位值、有序集的等段截分以及去邊界值問題等。這些問題的共性是,若用常規方法求解,系統無論在儲存開銷上還是處理開銷上都很大,而某些問題(如中值)的求解還相當難。本文將重述這些有趣的查詢問題及其解決方案。同時,我們還將討論「特徵函式」作為一種使能技術的其他一些應用可能。

2.特徵函式及其表示

特徵函式是來自點集拓撲學的乙個純數學概念,集合s的特徵函式定義如下:

1 若x? s

d s(x)= (0)

0 若x? s  

在這裡,任意元素x是否屬於集合s,決定函式取不同的值。同時,這裡也隱含了乙個前提,即任何元素的集合s為範圍的歸屬是完全確定的,不存在元素x的歸屬不明的情況。顯而易見,特徵函式是一種識別(或判定)裝置。正是這一特性,使它能夠成為資料庫查詢中選擇準則的一種等價(和更有效的)替換成分。因此,我們說特徵函式是加速

查詢的實施技術。

為了更直接地針對資料庫查詢問題,我們將特徵函式的一般形式變換成如下的「資料庫版本」:

1 若a=ture

d (a)= (1)

0 若a=false  

其中α是布林表示式。當構成布林表示式的算術表示式由表屬性及資料庫內部函式組成時,特徵函式的選擇作用就很清楚了。

眾所周知,一般關聯式資料庫採用三值邏輯,即布林表示式有可能取不確定值(「maybe」)。但為了簡化表達並因此突出特徵函式在加速

查詢中的本質作用,本文不考慮表屬性取不確定值的情形。另外,實現特徵函式的資料庫(內部)函式(我們稱之為特徵函式的「元函式」)會因系統和我們主觀選擇上的不同而不同。例如,sybase的transact sql有兩個很有用的內部函式abs()和sign(),可以直接作為特徵函式的元函式。若a和b是任意兩個表屬性,則:

d [a!=b]=abs(sign(a-b)) (2)

為了使元函式有定義,表屬性必須是數值變數。因此,除有特別宣告而外,本文將一概假定所有舉例和一般性討論中的表屬性為非空數值變數。等式(2)可從元函式的定義:

abs(a)=|a| (3)

-1 若a<0

sign(a)= 0 若a=0 (4)

+1 若a>0

直接推導出來。一般地,經abs()和sign()而實現的特徵函式是:

d [a=b]=1-abs(sign(a-b))

d [a!=b]=abs(sign(a-b)) (5)

d [a  d [a<=b]=sign(1-sign(a-b))

d [a>b]=1-sign(1-sign(a-b))

d [a>=b]=sign(1+sign(a-b)))

此外,設α和b 是任意布林表示式,則

d [notα]=1-d [α]

d [αandb ]=d [α]*d [b ] (6)

d [αor b ]=sign(d [α]+d [b ])

這裡的a和b是表屬性,為非空數值量。等式(5)給出了6個最簡單的特徵函式的元函式表示,但這並不是唯一的表示,還可能其他的表示方法。等式(6)是布林運算元的一般匯出規則。對於由最簡型式的關係表示式構成的布林表示式而言,等式(5)和(6)就構成其特徵函式的實現規則。對於一般布林表示式,等式(5)和(6)也是匯出其特徵函式的基礎。一般而言,由(5)和(6)可以推演出乙個特徵函式類,某些特徵函式直接對應於sql的選擇運算元。例如,形如d [a<=x<=b]的特徵函式顯然與判定變數x是否在閉區間[a,b]中有關。利用(5)中的第4個特徵函式及(6)中的第2個匯出規則:

d [a<=x<=b]

=d [(a<=x)and(x<=b)]

=d [a<=x]*d [x<=b]

=sign(1-sign(a-x))*sign(1-sign(x-b)) (7)

顯而易見,等式(7)右端的區則算術表示式恰是選擇運算元between的一種等價表達。可以仿照上述方法得到其他三個與區間值有關的特徵函式,即δ[a  

3. 例項分析

為了說明以上引入的特徵函式在加速

查詢處理中的作用,讓我們具體分析乙個例項。

試考察乙個描述學生收入狀況的表 students(name,status,parentincome,selfincome)(8)

其中name是主鍵,屬性status是一種標法量,當status取值1時,表明學生的收入完全來自父母,當status取值0時,表明學生的收入完全是自己勞動所得。針對這個表,假定我們想得到形如(name,income)的查詢結果,其中income或為學生自己的收入(當相應的status取0值時)或是來自父母的收入(當相應的status取值為1時)。

從表students的結構及查詢結果的語義分析,完成查詢的常規方法應當是:

select name,income=parentincome

from student

where student=1 union (9)

select name , income=selfincome

from student

where student=0

這是乙個很自然、很直白的查詢表達,但同時也是乙個非常低效和非常耗費資源的表達。執行這個查詢的一般過程是:首先分別執行由運算元union所鏈結的兩個子查詢,然後產生乙個存放查詢中間結果的臨時表並將兩個子查詢的結果存入以這個臨時表中,第3步對臨時表作排序以便消除可能存在的重複值。至此,才得到最終的查詢結果。在這樣的處理中,除對整個表students要遍歷兩次而且要對中間結果作排序處理,處理上的煩雜和資源的消耗都是顯而易見的。查詢(9)唯一的優點,是它表達上的自然直白,誰都想得到。

對本例而言,還有更緊湊和更有效的查詢表達。例如,不難驗證以下的查詢:

seiect name,income=parentincome*status+selfincome*(1-status)

from students; (10)

從語義上與查詢(9)完全等價。但查詢(10)不但消耗的儲存少而且處理上要有效得多,因為它只遍歷一次表students而且避免了可怕的排序操作。這個例子說明,對同乙個查詢結果,不同的查詢表達在處理效率和資源消耗上可能會相去甚遠。因此,尋求有效的查詢表達方式,不但是必要的而且是可行的。

查詢表達(10)與像(9)那樣的常規表達不同之處在於,後者的查詢條件由兩個where子句和運算元union顯式給出,首者將查詢條件間接地隱藏在select子句的算術表示式中。無論查詢表達採用什麼形式,本例都屬於「條件檢索」的查詢型別。如果對照一下查詢要求和查詢表達(10),不難發現只所以能給出如此簡潔而正確的回簽,實在是有點「事有湊巧」。如果問題稍作些許改變(例如,屬性student取0和1以外的值,或者student取兩個以上的標法值,如此等等)問題就不會這麼簡單了。因此,是否有一種很一般、很系統的解決方案,能讓我們對任何顯式表達在where子句和相關運算元中的選擇條件找到與之語義等價的算術表示式?答案是肯定的。

sql中查詢日期的函式

datediff函式 日期部分 縮寫 year y,yyyy quarter qq,q month mm,m dayofyear dy,y day dd,d week wk,ww hour hh minute mi,n second ss,s millisecond ms 查詢本日的記錄 selec...

sql concat函式 SQL 的複雜查詢

1.檢視 定義 檢視是存放sql語句的臨時表,無需儲存資料,節省空間 可隨原表資料變化而自動更新。形式 creat view 檢視名稱 檢視列名1 檢視列名2 as 檢視列名稱和查詢列順序是一一對應的。注意事項 1 不要在檢視基礎上再次建立檢視 2 不在檢視裡面插入資料 2.子查詢 1 書寫格式 s...

SQL的搜尋查詢,函式(初始階段)

例子 插入多條資料 複製資料到舊表 例子 複製到新錶 例子 例子 truncate刪除 例子 例子 查詢表中指定列的資訊 例子 格式 例子 查詢符合條件的資訊 例子 查詢一定量的資料 例子 按條目數查詢 查詢非空的 賴子 字符集 字符集取反 範圍查詢 例子 select from goods whe...