[導(dǎo)讀]數(shù)據(jù)庫(kù)JDBC有多慢JAVA應(yīng)用必須通過(guò)JDBC從數(shù)據(jù)庫(kù)中取數(shù),有時(shí)候我們會(huì)發(fā)現(xiàn),數(shù)據(jù)庫(kù)的負(fù)擔(dān)一點(diǎn)也不重而且SQL很簡(jiǎn)單,但取數(shù)的速度仍然很慢。我們來(lái)實(shí)際測(cè)試一下,有個(gè)感性認(rèn)識(shí),以O(shè)racle為例。數(shù)據(jù)來(lái)源使用TPCH生成的數(shù)據(jù),選用其中的customer表來(lái)做測(cè)試,數(shù)據(jù)記錄為1...
數(shù)據(jù)庫(kù)JDBC有多慢JAVA 應(yīng)用必須通過(guò) JDBC 從數(shù)據(jù)庫(kù)中取數(shù),有時(shí)候我們會(huì)發(fā)現(xiàn),數(shù)據(jù)庫(kù)的負(fù)擔(dān)一點(diǎn)也不重而且 SQL 很簡(jiǎn)單,但取數(shù)的速度仍然很慢。我們來(lái)實(shí)際測(cè)試一下,有個(gè)感性認(rèn)識(shí),以O(shè)racle為例。數(shù)據(jù)來(lái)源使用TPCH生成的數(shù)據(jù),選用其中的customer表來(lái)做測(cè)試,數(shù)據(jù)記錄為1500萬(wàn)行,8個(gè)字段。它生成的原始文本文件名為customer.tbl,文件大小為2.3G。利用數(shù)據(jù)庫(kù)提供的數(shù)據(jù)導(dǎo)入工具將此文件數(shù)據(jù)導(dǎo)入到Oracle的數(shù)據(jù)表中。測(cè)試環(huán)境CPU:2顆Intel3014,主頻1.7G,每個(gè)CPU內(nèi)核數(shù)6個(gè)。硬盤(pán)(SSD):1T 561MB/s(讀) 523MB/s(寫(xiě)) 接口:SATA 6.0Gb/s內(nèi)存:64G。操作系統(tǒng):Linux CentOS 7所有測(cè)試均在服務(wù)器本機(jī)上完成,沒(méi)有消耗網(wǎng)絡(luò)傳輸時(shí)間。數(shù)據(jù)庫(kù)讀數(shù)測(cè)試通過(guò)Oracle提供的JDBC接口,用SQL語(yǔ)句執(zhí)行數(shù)據(jù)讀取。Java寫(xiě)起來(lái)麻煩,用SPL腳本執(zhí)行測(cè)試:
|
A
|
B
|
1
|
=now()
|
/記錄時(shí)間
|
2
|
=connect("oracle")
|
/連接數(shù)據(jù)庫(kù)
|
3
|
=A2.cursor("SELECT * FROM CUSTOMER")
|
/生成取數(shù)游標(biāo)
|
4
|
for A3,10000
|
/循環(huán)取數(shù),每次10000條
|
5
|
=A2.close()
|
/關(guān)閉連接
|
6
|
=interval@s(A1,now())
|
/計(jì)算時(shí)長(zhǎng)
|
測(cè)試結(jié)果:275秒文本文件對(duì)比測(cè)試只從上面的測(cè)試結(jié)果來(lái)看,還沒(méi)有太多感性認(rèn)識(shí),我們?cè)僮x一下文本文件來(lái)對(duì)比。辦法是一樣的,從文件中讀出數(shù)據(jù),并解析出記錄,不作任何計(jì)算。編寫(xiě)如下SPL腳本執(zhí)行測(cè)試:
|
A
|
B
|
1
|
=now()
|
/記錄時(shí)間
|
2
|
=file("customer.tbl")
|
/文件對(duì)象
|
3
|
=A2.cursor(;,"|")
|
/生成取數(shù)游標(biāo),分隔符是|
|
4
|
for A3,10000
|
/循環(huán)取數(shù),每次10000條
|
5
|
=interval@s(A1,now())
|
/計(jì)算時(shí)長(zhǎng)
|
測(cè)試結(jié)果:43秒這意味著,讀取文本要比讀取Oracle快275/43=6.4倍。我們知道,文本解析是個(gè)非常麻煩的事情,但即使這樣,從文本文件讀取數(shù)據(jù)還是遠(yuǎn)遠(yuǎn)快于從數(shù)據(jù)庫(kù)中讀數(shù)。
利用集算器 SPL并行提速當(dāng)數(shù)據(jù)只能從數(shù)據(jù)庫(kù)讀取,而且數(shù)據(jù)庫(kù)本身負(fù)擔(dān)并不重時(shí),我們可以利用多 CPU 并行方案來(lái)提速,但寫(xiě)Java 的并行程序非常麻煩,要考慮資源共享沖突等問(wèn)題。使用集算器SPL的并行技術(shù)可以提升數(shù)據(jù)庫(kù)JDBC取數(shù)性能,避免 JAVA 硬編碼的復(fù)雜性,方便實(shí)現(xiàn)多線程結(jié)果集的合并。下面我們來(lái)測(cè)試一下。單表并行取數(shù)還是上面的這張customer表 ,改為并行取數(shù)后,可以看到性能提升明顯,代碼如下:
|
A
|
B
|
1
|
=now()
|
/記錄時(shí)間
|
2
|
=connect("oracle").query@ix("SELECT COUNT(*) FROM CUSTOMER")(1)
|
3
|
>n=12
|
/并行數(shù)
|
4
|
=n.([int(A2/n)*(~-1),int(A2/n)*~])
|
/按并行數(shù)分段區(qū)間
|
5
|
fork A4
|
=connect("oracle")
|
6
|
|
=B5.query@x("SELECT * FROM CUSTOMER WHERE C_CUSTKEY>? AND C_CUSTKEY<=?",A5(1),A5(2))
|
7
|
=A5.conj()
|
/合并結(jié)果
|
8
|
=interval@s(A1,now())
|
/計(jì)算時(shí)長(zhǎng)
|
測(cè)試結(jié)果:28秒(非并行用時(shí)275秒)并行取數(shù),就要把源數(shù)據(jù)分成相對(duì)平均的多個(gè)區(qū)間。本例中,C_CUSTKEY是從1開(kāi)始的自然數(shù),因此可以先求出總記錄數(shù)(A2),再用平均分成n段(A4)。然后 A5并行計(jì)算,每個(gè)線程各自連接數(shù)據(jù)庫(kù),再以C_CUSTKEY區(qū)間為參數(shù)執(zhí)行SQL。最后合并多線程的取數(shù)結(jié)果,作為最終結(jié)果。 實(shí)際情況中,可能需要采取其它辦法設(shè)置WHERE條件以獲得相對(duì)平均的區(qū)間。多表并行取數(shù)有時(shí)候是多個(gè)SQL取數(shù),也可以利用并行方法來(lái)提速。還是使用TPCH生成的數(shù)據(jù),數(shù)據(jù)總量減少為5G,選用其中的5張表來(lái)做測(cè)試。當(dāng)采用非并行取數(shù)時(shí),可以發(fā)現(xiàn)性能不夠理想,代碼如下:
|
A
|
B
|
1
|
SELECT * FROM SUPPLIER
|
|
2
|
SELECT * FROM PART
|
|
3
|
SELECT * FROM CUSTOMER
|
|
4
|
SELECT * FROM PARTSUPP
|
|
5
|
SELECT * FROM ORDERS
|
|
6
|
=now()
|
/記錄時(shí)間
|
7
|
=connect("oracle")
|
/連接數(shù)據(jù)庫(kù)
|
8
|
=[A1:A5].(A7.query(~))
|
/順序執(zhí)行每條SQL
|
9
|
>A7.close()
|
/關(guān)閉連接
|
10
|
=interval@ms(A6,now())
|
/計(jì)算時(shí)長(zhǎng)
|
測(cè)試結(jié)果:360秒改為并行取數(shù)后,可以看到性能提升明顯,代碼如下:
11
|
=now()
|
/記錄時(shí)間
|
12
|
fork [A1:A5]
|
=connect("oracle")
|
13
|
|
=B12.query@x(A12)
|
14
|
=interval@ms(A11,now())
|
/計(jì)算時(shí)長(zhǎng)
|
測(cè)試結(jié)果:167秒盡管多表并行無(wú)法保證數(shù)據(jù)均勻分布,但并行計(jì)算也能讓取數(shù)性能得到有效提升。集算器 SPL 是 Java 寫(xiě)的開(kāi)源軟件,提供了 JDBC 接口,很容易集成到 Java 應(yīng)用中。
欲知詳情,請(qǐng)下載word文檔
下載文檔
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。