您好,登錄后才能下訂單哦!
很多算法都會(huì)產(chǎn)生落地的中間結(jié)果,從而影響性能,尤其是數(shù)據(jù)量較大的時(shí)候。這種情況下通??捎贸绦蛴螛?biāo)來(lái)避免數(shù)據(jù)落地,下面舉例說(shuō)明。
計(jì)算目標(biāo):訂單表原來(lái)已按時(shí)間排序,需要將數(shù)據(jù)按日期、產(chǎn)品去除重復(fù),再統(tǒng)計(jì)記錄條數(shù)。
由于去重后結(jié)果集較大,內(nèi)存放不下,因此一般會(huì)用groupx去重,SPL腳本如下:
A | ||
1 | =file("sales.btx").cursor@b() | /從集文件讀入訂單記錄 |
2 | =A1.groupx(date(ORDERDATE),PRODUCTID) | /按日期、產(chǎn)品分組去重 |
3 | =A2.skip() | /對(duì)游標(biāo)計(jì)數(shù) |
但函數(shù)groupx會(huì)導(dǎo)致數(shù)據(jù)落地,因此性能不高。
要使去重的中間結(jié)果不落地,可以先生成程序游標(biāo),distinctProduct.dfx腳本如下:
A | B | |
1 | =file("sales.btx").cursor@b() | |
2 | for A1;date(ORDERDATE) | =A2.id(PRODUCTID) |
3 | return B2 |
A2:循環(huán)訂單表。由于數(shù)據(jù)已按時(shí)間排序,因此每次取日期相同的一批數(shù)。
B2:按產(chǎn)品去重。注意,全量數(shù)據(jù)雖大,但按天取數(shù)相對(duì)較少,內(nèi)存可以放下,所以這里用id去重。
B3:返回本批次的去重結(jié)果。注意,程序游標(biāo)并非一次性返回所有數(shù)據(jù),而是每次循環(huán)之后,先等待調(diào)用者的請(qǐng)求,如果調(diào)用者繼續(xù)要數(shù)據(jù),程序游標(biāo)才會(huì)進(jìn)行下一次循環(huán),期間數(shù)據(jù)不落地。
主程序可通過(guò)cursor函數(shù)調(diào)用程序游標(biāo),用法與普通游標(biāo)類(lèi)似:
A | ||
1 | =cursor("distinctProduct.dfx") | /調(diào)用程序游標(biāo) |
2 | =A1.skip() |
可以看到,程序游標(biāo)可減少數(shù)據(jù)落地,從而提升計(jì)算性能。
數(shù)據(jù)庫(kù)進(jìn)行集合運(yùn)算時(shí)要先排序,如果數(shù)據(jù)量太大,則排序會(huì)耗費(fèi)大量時(shí)間,遲遲不能輸出結(jié)果。在這種情況下,適合用程序游標(biāo)生成不落地的有序中間結(jié)果集,從而實(shí)現(xiàn)快速輸出。
比如兩張結(jié)構(gòu)相同表:callRecordA、callRecordB。兩張表在時(shí)間字段callTime上建立了索引,每秒數(shù)據(jù)量萬(wàn)級(jí),現(xiàn)在對(duì)2015-01-01這一天的數(shù)據(jù)做并集運(yùn)算,需要快速輸出前500條(比如在報(bào)表上快速呈現(xiàn))。
這次將程序游標(biāo)和調(diào)用代碼寫(xiě)在同一個(gè)腳本中,如下:
A | B | C | |
1 | func | =connect("orcl") | |
2 | for 60*60*24 | =elapse(datetime("2015-01-01 00:00:00"),A2-1) | |
3 | =A1.query("select CALLTIME,OUTID,INID,DURATION,CHARGE from"+A1+"where callTime=?",B2) | ||
4 | =B3.sort(OUTID,INID,DURATION,CHARGE) | ||
5 | return B4 | ||
6 | =A1.close() | ||
7 | =cursor@c(A1,"callRecordA") | ||
8 | =cursor@c(A1,"callRecordB") | ||
9 | =[A7,A8].mergex@u() | ||
10 | =A9.fetch@x(500) |
A1:用func定義程序游標(biāo),相應(yīng)的調(diào)用語(yǔ)法為cursor@c。
B2:循環(huán)一天中的每一秒。
C3:從數(shù)據(jù)庫(kù)查詢(xún)一秒的數(shù)據(jù),因?yàn)槭前此饕?shù),所以速度很快,而且對(duì)數(shù)據(jù)庫(kù)影響很小。注意A1是表名變量,程序游標(biāo)既可以從callRecordA取數(shù),也可以從callRecordB取數(shù)。
C4:對(duì)一秒數(shù)據(jù)進(jìn)行內(nèi)存排序,以便形成有序結(jié)果集。由于數(shù)據(jù)在同一秒,所以只需對(duì)其他字段排序。
A7A8:以表名為參數(shù),取出2個(gè)程序游標(biāo)。
A9:對(duì)兩個(gè)游標(biāo)進(jìn)行有序歸并,@u表示取并集。類(lèi)似地,可以用@i和@d分別進(jìn)行并交集、差集運(yùn)算。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。