日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.2 使用窗口函数的解决方案简介...

發(fā)布時間:2023/12/4 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.2 使用窗口函数的解决方案简介... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本節(jié)書摘來自異步社區(qū)出版社《T-SQL性能調(diào)優(yōu)秘笈——基于SQL Server 2012 窗口函數(shù)》一書中的第1章,第1.2節(jié),作者: 【美】Itzik Ben-Gan,更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“異步社區(qū)”公眾號查看。

1.2 使用窗口函數(shù)的解決方案簡介

T-SQL性能調(diào)優(yōu)秘笈——基于SQL Server 2012 窗口函數(shù)
本書前4章描述了窗口函數(shù)及其優(yōu)化,所選素材偏重技術說明,雖然我自己覺得很吸引人,但可以想見,有些人會覺得有點沉悶。通常來說,人們在閱讀用窗口函數(shù)解決現(xiàn)實問題的內(nèi)容時,會覺得比較有趣,本書將在最后一章滿足大家。只有當我們看到能如何用窗口函數(shù)解決難題時,才會真正認識到它們的價值。所以,我在思考如何說服你在讀到有趣的章節(jié)之前,能堅持讀完這些枯燥的技術說明而不中途放棄。也許我可以展示一個窗口函數(shù)解決方案示例。

這里演示的查詢包含:對一個在列中包含序列號的表進行查詢,在現(xiàn)有值中找到連貫的區(qū)間。這個難題也就是所謂的數(shù)據(jù)島問題。序列號可以是數(shù)值類型的、時間類型的(比較常見)或支持全排序的任意數(shù)據(jù)類型。序列號可以是唯一值,也可以是重復值。間隔可以是任何符合列類型(如,整型數(shù)1、整型數(shù)7、時間間隔為1天、時間間隔為2周等)的固定間隔。第5章會講述間隔的各種變化。這里只舉個簡單的案例,讓大家感受一下窗口函數(shù)是如何工作的——所以用數(shù)值序列,間隔為1,首先用下面的代碼來生成樣本數(shù)據(jù):

在表T1中,可以看到col1的序列號并不連續(xù)。我們的任務是找到現(xiàn)有值的連續(xù)區(qū)間(也稱為數(shù)據(jù)島,)返回每個數(shù)據(jù)島的開始值和結(jié)束值,我們希望得到的結(jié)果如下:

如果我們好奇這類問題在現(xiàn)實中的使用場景,這里有很多實際例子。示例包括生成可用性報告,識別某種活動的持續(xù)時間(如,銷售活動),找到滿足一定要求的持續(xù)區(qū)間(如,股票高于或低于一定閾值的時間區(qū)間),識別車牌的使用范圍等。當前示例的目的非常簡單,我們可以專注在實現(xiàn)它的技術上。只須稍作調(diào)整,應用在簡單案例上的技術就可以應用在更加復雜的案例上,所以請把它看成是一個基于集合的解決方案帶來的挑戰(zhàn)。首先請找出一個能解決問題的方案,然后對表填充大量的數(shù)據(jù)行(假設10 000 000行)然后再試試剛才的解決方案,看看它將如何進行。完成這些,我們再來看我的解決方案。

在展示使用窗口函數(shù)的方案之前,我先展示其中一個用傳統(tǒng)語言結(jié)構(gòu)實現(xiàn)的解決方案。特別地,我會展示使用子查詢的解決方案。為了解釋第一種解決方案的策略,先查看T1.col1序列的值,我增加了一個目前尚不存在的概念化的列,把它當做組標識符:

grp列尚未存在,從概念上來說,它的值唯一地標識一個數(shù)據(jù)島。這就意味著,對同一個島內(nèi)的所有成員,它們的grp值相同,并與其他島內(nèi)的成員的grp值不同。如果我們能設法對這樣的組標識符進行計算,我們就能把結(jié)果根據(jù)grp特性值進行分組,返回每組(島)中最大和最小的col1值。傳統(tǒng)語言結(jié)構(gòu)中生成這個組標識符的方法是:針對col1的每個當前值,找到大于或等于當前值的最小的col1值,并且要求這個值后面沒有值。

舉例說明,按照上面的邏輯,試著找到相對于值2,col1的值大于或等于2的最小值,且要求其后面的值沒有連續(xù),答案是3。現(xiàn)在,針對3,做同樣的查找,結(jié)果還是3,所以3是組標識符,數(shù)據(jù)島開始于2,結(jié)束于3。對于開始于11,結(jié)束于13的數(shù)據(jù)島,組成員的標識符都是13。從這里我們可以看到,一個數(shù)據(jù)島內(nèi)的所有成員的組標識符,實際上就是數(shù)據(jù)島最后一個成員的值。

下面是實現(xiàn)這個概念的T-SQL代碼。

代碼執(zhí)行后的輸出結(jié)果如下:

下面的部分就相當直觀了——根據(jù)上面的查詢定義表表達式,在外部查詢中,根據(jù)組標識符進行分組,返回每組的最大和最小的col值,如下。

在這個解決方案里,有兩個主要問題。一、這里遵循的邏輯有點復雜。二、運行非常緩慢。我暫時不想開始討論查詢執(zhí)行計劃——后面的篇幅有很多這方面的討論——在這兒可以告訴大家,針對表中的每一行,SQL Server都幾乎執(zhí)行了兩次完整的數(shù)據(jù)掃描。現(xiàn)在可以想象對于10 000 000條記錄組成的序列,嘗試轉(zhuǎn)化它對應的工作量會有多少了。需要處理的行的數(shù)量只有一個詞形容——巨大。

另一個解決方案也是計算組標識符,不同之處是,使用窗口函數(shù)進行。解決方案的第一步是使用ROW_NUMBER函數(shù)基于col1排序計算行號。本書后面會提供ROW_NUMBER的細節(jié)。目前,只要知道它在分區(qū)中,按照給定的順序,從1開始,逐一遞增,產(chǎn)生唯一的整數(shù)就足夠了。

牢記上面的知識,下面的查詢按照col1排序,返回的col1的值和行號。

現(xiàn)在,我把注意力集中到兩個序列上。一個(col1)是不連貫的,另一個(rownum)是連貫的。記住這一點,然后嘗試發(fā)現(xiàn)在一個數(shù)據(jù)島內(nèi),二者有什么獨特的關系。在數(shù)據(jù)島內(nèi),兩個序列都以固定間隔在增長,因此,二者的差異是一個常數(shù)。在另一個島內(nèi),col1的增量超過1,而rownum的增量還是1,所以差異在變大。換句話說,二者的差異是常數(shù),不同數(shù)據(jù)島內(nèi)的數(shù)值不同。運行下面的查詢來計算其差異。

我們可以看到,這個差異滿足我們對組標識符的兩個需求,因此,可以把它當做組標識符使用。其他內(nèi)容都與之前的解決方案相同,即是說,把行按組標識符進行分組,返回每組中最小和最大的col1值,如下所示。

請觀察一下,這樣的解決方案多么清晰和簡單。同時,在代碼上加上注釋,幫助那些第一次讀代碼的人更好地了解解決方案,也是個不錯的主意。

這個解決方案還很高效。與前一解決方案相比,其所涉及的行的處理數(shù)量微不足道。它僅僅包含一個在col1上的排序索引掃描和一個持續(xù)遞增計數(shù)器的迭代器。我測試過這條查詢的性能,它在10 000 000條記錄組成的序列上僅運行了10秒鐘。前一解決方案的運行時間就要長得多。

希望關于使用窗口函數(shù)的解決方案的簡介,能足以吸引你,讓你看到它們包含的強大功能。現(xiàn)在,我們要返回繼續(xù)學習窗口函數(shù)技術了,在書的后面部分,我們還有機會看到更多的示例。

本文僅用于學習和交流目的,不代表異步社區(qū)觀點。非商業(yè)轉(zhuǎn)載請注明作譯者、出處,并保留本文的原始鏈接。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.2 使用窗口函数的解决方案简介...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。