您好,登錄后才能下訂單哦!
排號鍵是SPL獨特的數(shù)據(jù)類型,適合替代多層次、各層不連續(xù)的鍵值,比如×××號、合同編號、產(chǎn)品編號、組織機構(gòu)代碼等。排號鍵定位速度快,常用于優(yōu)化內(nèi)存索引查詢和外鍵關(guān)聯(lián)計算。
cardNormal.btx是集文件格式的×××信息表,數(shù)據(jù)量一百萬條,字段為:cardNo(×××,主鍵),name(姓名),gender(性別),province(省份),email(電子郵件),mobile(移動電話),address(住址)。cardK.btx與cardNormal.btx在結(jié)構(gòu)和數(shù)據(jù)上完全相同,唯一的區(qū)別在于cardNo字段是排號鍵。
本案例對cardNormal.btx和cardK.btx分別執(zhí)行百萬次索引查詢,并比較兩者性能。
其中cardNo是簡化后的×××,格式如下:
位數(shù) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
規(guī)則 | 行政區(qū)劃 | 生日 | 流水 | 校驗 | ||||||||||||
細則 | 省 | 地區(qū) | 年 | 月 | 日 | 流水 | 校驗 | |||||||||
范例 | 1 | 0 | 0 | 3 | 1 | 9 | 8 | 0 | 1 | 2 | 1 | 3 | 0 | 2 | 3 | x |
省、地區(qū):各自取值范圍為1-10。
生日:取值為"1980-06-01"至"1981-01-01"。
流水:取值為1-100。
校驗:根據(jù)前15位計算出的冗余校驗位,取值為0至10,其中10用x來表示。
將上述×××轉(zhuǎn)為排號鍵,可采取如下思路:
1. 省、地區(qū):排號鍵的每一層只支持1-255的整數(shù),因此將省和地區(qū)分別轉(zhuǎn)為整數(shù),作為第1、2層排號鍵。
2. 生日:排號鍵以1為起始,可以取得更好的性能,因此算出原生日和1980-06-01的間隔天數(shù),作為第3層排號鍵。
3. 流水:轉(zhuǎn)為整數(shù),作為第4層的排號鍵。
4. 校驗位:冗余數(shù)據(jù),可刪除。
具體轉(zhuǎn)換腳本如下:
k(int(mid(cardNo,1,2)), int(mid(cardNo,3,2)), interval("1980-06-01",date(mid(cardNo,5,8),"yyyyMMdd")), int(mid(cardNo,13,3)) ) |
下面對cardNormal.btx和cardK.btx分別執(zhí)行百萬次索引查詢。
A | B | C | |
1 | =cardNormal=file("d:\\temp\\cardNormal.btx").import@b().keys(cardNo).index() | /將cardNormal.btx讀入內(nèi)存 | |
2 | =paramList=cardNormal.(cardNo).sort(rand()).to(100000) | /隨機取1萬個××× | |
3 | |||
4 | =now() | ||
5 | for 100 | =paramList.(cardNormal.find(~)) | /查詢百萬次 |
6 | =interval@ms(A4,now()) | /字符串鍵性能:5537ms | |
7 | |||
8 | =cardK=file("d:\\temp\\cardk.btx").import@b().keys(cardNo).index@s() | /將cardk.btx讀入內(nèi)存 | |
9 | =paramListK=paramList.(k(int(mid(~,1,2)), int(mid(~,3,2)), interval("1980-06-01",date(mid(~,5,8),"yyyyMMdd")), int(mid(~,13,3)) )) | /將字符串參數(shù)轉(zhuǎn)為排號鍵參數(shù) | |
10 | =now() | ||
11 | for 100 | =paramListK.(cardK.find(~)) | /查詢百萬次 |
12 | =interval@ms(A10,now()) | /排號鍵性能:1977ms |
A8:對排號鍵建立內(nèi)存哈希索引,需使用函數(shù)選項@s。
可以看到,對字符串鍵建立索引,查詢需耗費5547毫秒,而排號鍵只需1977毫秒,后者明顯快。
taxNormal.btx是集文件格式的報稅信息表,數(shù)據(jù)量一千萬條,字段為:serial(主鍵,流水號),cardNo(外鍵,×××),tax(報稅額),area(所屬地區(qū)),declaretype(申報類型),unit(申報單位),declareTime(申報時間),network(辦理網(wǎng)點)。taxK.btx 與taxNormal.btx在結(jié)構(gòu)和數(shù)據(jù)上完全相同,唯一的區(qū)別在于cardNo字段是排號鍵。
本案例算法:
1. 對taxNormal.btx和cardNormal.btx進行外鍵關(guān)聯(lián)計算,排除操作系統(tǒng)緩存和硬盤IO的影響,只取關(guān)聯(lián)動作消耗的時間。
2. 對taxK.btx和cardK.btx進行外鍵關(guān)聯(lián)計算,排除操作系統(tǒng)緩存和硬盤IO的影響,只取關(guān)聯(lián)動作消耗的時間。
3. 比較1和2的差異。
具體算法如下:
A | B | C | |
1 | =file("d:\\temp\\taxNormal.btx").cursor@b() | for A1,10000 | /打開報稅表,預遍歷游標 |
2 | =A1.reset() | /重置游標到起點 | |
3 | =file("d:\\temp\\cardNormal.btx").import@b().keys(cardNo).index() | /打開×××表 | |
4 | =now() | ||
5 | for A1,10000 | /正式遍歷游標 | |
6 | =interval@ms(A4,now()) | =A1.reset() | /遍歷游標耗時3748ms |
7 | =A1.switch(cardNo,A3:cardNo) | for A1,10000 | /建立關(guān)聯(lián),預遍歷游標 |
8 | =A1.reset() | /重置游標到起點 | |
9 | =now() | ||
10 | for A7,10000 | /正式遍歷關(guān)聯(lián)游標 | |
11 | =interval@ms(A9,now()) | =A11-A6 | / 建立關(guān)聯(lián)耗時:7553ms |
12 | /上面:字符串鍵關(guān)聯(lián)。下面:排號鍵關(guān)聯(lián) | ||
13 | =file("d:\\temp\\taxK.btx").cursor@b() | for A13,10000 | /打開報稅表,預遍歷游標 |
14 | =A13.reset() | /重置游標到起點 | |
15 | =file("d:\\temp\\cardK.btx").import@b().keys(cardNo).index@s() | /打開×××表 | |
16 | =now() | ||
17 | for A13,10000 | /正式遍歷游標 | |
18 | =interval@ms(A16,now()) | =A13.reset() | /遍歷游標耗時2884ms |
19 | =A13.switch(cardNo,A15:cardNo) | for A19,10000 | /建立關(guān)聯(lián),預遍歷游標 |
20 | =A19.reset() | /重置游標到起點 | |
21 | =now() | ||
22 | for A19,10000 | /正式遍歷關(guān)聯(lián)游標 | |
23 | =interval@ms(A21,now()) | =A23-A18 | /建立關(guān)聯(lián)耗時:966ms |
B2、B7、B13、B19:預遍歷游標,避免操作系統(tǒng)緩存的影響。遍歷之后需用reset函數(shù)重置游標,以便后續(xù)再次遍歷。
B11、B23:用總時間減去遍歷時間,獲得關(guān)聯(lián)動作消耗的時間。
可以看到,用普通鍵做外鍵關(guān)聯(lián)計算,其關(guān)聯(lián)動作耗時7553ms;排號鍵做外鍵關(guān)聯(lián)計算時,只需耗時966ms,后者明顯快。而且可以看出,使用排號鍵讀出記錄(fetch)的時間也少于使用字符串(其它字段和記錄行數(shù)都相同),說明排號鍵對象的生成性能更好。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。