青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 297,  comments - 15,  trackbacks - 0
Dejan Bosanac是一個軟件開發者,技術顧問和作家。他關注不同技術的集成和互操作,尤其是與Java以及Web開發相關的領域。

數據庫在操作少量測試數據和大量數據的時候,表現行為上有很大的差異。通常,在開發過程前期,人們不會關注數據庫性能的問題,但是隨著時間的發展,人們必須采取一些措施來保證數據庫在大量數據的情況下正常工作。

Derby這個完全Java開發的開源的數據庫也不例外,因此你必須保證它不會成為你程序的一個瓶頸。盡管人們可以在Derby的手冊中找到關于這 個話題全面的資料,我還是想更詳盡的關注一下這些問題,基于我的經驗提供一些具體的例子。本文將著重于那些由在大的數據表中選擇查詢數據而產生的程序性能 問題。

首先,有很多關于調整Derby屬性(諸如頁面大小和緩存大小等)的技巧。修改這些參數可以在一定程度上調整數據庫的性能,但是在通常情況下,更主要的問題來自與你的程序和數據庫的設計,因此,我們必須首先關注這些問題,最后再來考慮Derby的屬性。

在接下來的段落里,我將介紹一些能夠優化程序中有問題部分的技術。但是,和其他性能優化操作一樣,我們需要在優化前先測量并確認問題所在。

一個簡單的例子

讓我們從一個簡單的例子開始:假設我們Web程序中擁有一個“search/list”的頁面,要處理一個有接近100,000行的表,并且那個表 不是很小的(至少有10欄)。用簡單的JDBC來寫一個例子,這樣我們可以專注在數據庫和JDBC問題上來。這篇文章中介紹的所有準則對所有的面向對象的 映射工具都適用。

為了使得用戶能夠列出一個大的表,通常使用下面簡單的查詢語句。 select * from tbl


對應的JDBC語句如下:Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection (
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from tbl");
ArrayList allResults = new ArrayList();
while (rs.next()) {
// Object-Relation mapping code to populate your
// object from result set row
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
System.out.println("Results Size: " + allResults.size());


在這兒,我們碰到了第一個問題。執行這樣的代碼,并產生100,000(或更多)個domain對象將肯定會導致java用完堆棧空間,產生一個 “java.lang.OutOfMemoryError”的錯誤。對于初學者來說,我們首先必須找到一個方法來使得這個程序工作。

分頁Result Sets

隨著程序中數據量的增多,你首先想到的應該做的事就是為特定的記錄(通常是視圖)提供分頁支持。正如你在這個介紹性的例子中看到的,簡單地去獲取龐大的result sets很容易導致 out of memory的錯誤。

許多數據庫服務器支持特定的SQL結構,它們可以用于獲得一個查詢結果的特定的子集。例如,在MySQL中,提供了LIMIT和OFFSET關鍵字,它們可以用于select查詢。因此,如果你執行類似下面的查詢:select * from tbl LIMIT 50 OFFSET 100 


你的結果集將包含從第100個結果開始的50行,即使原先的查詢返回了100,000行。許多其他的數據庫提供商通過不同的結構提供了相似的功能。 不幸的是,Derby并沒有提供這樣的功能,所以你必須繼續使用原先的“select * from tbl”查詢語句,然后在應用程序中實現一個分頁的機制。讓我們來看下面的例子:Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection(
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM tbl");
ArrayList allResults = new ArrayList();
int i = 0;
while (rs.next()) {
if (i > 50 && i <= 100) {
// O-R mapping code populate your row from result set
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
i++;
}
System.out.println("Results Size: " + allResults.size());


通過這些額外的語句,我們提供了“分頁”的功能。盡管所有的結果都從數據庫服務器中取出了,但是只有那些我們感興趣的行才真正的映射到了Java的 對象中。現在我們避免了先前碰到的“OutOfMemoryError”的問題了,這樣保證了我們的程序可以真正的工作在大的數據表上。

然而,通過這個解決方案,數據庫仍然會掃描整個表,然后返回所有的行,這還是一個非常消耗時間的任務。對于我的事例數據庫來說,這個操作的執行要花費10秒鐘,這在程序中顯然是不可接受的。

因此,我們必須給出一個解決方案;我們并不需要返回所有的數據庫行,而只需要那些我們感興趣的(或者至少是所有行的最小可能子集)。我們這兒使用的 技巧就是顯式的告訴JDBC驅動我們需要多少行。我們可以使用java.sql.Statement接口提供的setMaxRows()函數來完成這個任 務。看下面的例子:Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection connection = DriverManager.getConnection(
"jdbc:derby://localhost:1527/testDb;");
Statement stmt = connection.createStatement();
stmt.setMaxRows(101);
ResultSet rs = stmt.executeQuery("SELECT * FROM tbl");
ArrayList allResults = new ArrayList();
int i = 0;
while (rs.next()) {
if (i > 50 && i <= 100) {
// O-R mapping code populate your row from result set
DomainObject domainObject = populate(rs);
allResults.add(modelObject);
}
}
System.out.println("Results Size: " + allResults.size());


值得注意的是,我們把最大行的值設置為了我們需要的最后一行(增加了1)。因此,通過這樣的解決方案,我們不是僅僅取得了我們想要的50行,而是先 獲取了100行,然后從中篩選出我們感興趣的50行。不幸的是,我們沒有辦法告訴JDBC驅動從一個具體的行開始,因此我們必須說明要顯示的記錄的最大行 數。這就意味著返回最初的一些記錄的操作的性能是很好的,但是隨著用戶瀏覽的結果的增多,性能也會下降。好消息就是在大多數的情形下,用戶不會瀏覽的太多 的記錄,他們會在前幾條記錄重獲得他們尋找的行,或者改變查詢策略。在我本人的環境中,上述的例子的執行時間從8秒降到了0.8秒。

這是一個描述如何瀏覽整個表的簡單的例子。但是當查詢語句中增加了特定的where條件和排序信息時,事情又開始變化了。在接下來的部分里,我將解釋為什么這種情況會發生,以后我們如何保證在那些例子中獲得可接受的性能。
確保使用索引(避免全表掃描)

索引在數據庫設計中是一個非常重要的概念。因為本文所涉及的范圍有限,我并不會詳細的介紹索引理論。簡單來說,索引是特定的數據庫結構,能夠允許對 表中的行進行快速訪問。索引通常是在一欄或多欄上創建的,因為他們比整個表小了很多,他們的主要用處就是快速搜索一欄(多欄)中的值。

Derby自動的為主鍵和外鍵的欄以及具有唯一性限制的欄創建索引。對于其他任何欄,我們必須顯式的創建索引。在接下來的段落中,我們將研究一些例子來介紹索引在什么時候有用以及為什么有用。

但是首先,我們必須做一些準備。在我們開始優化之前,我們需要能夠了解我們執行查詢操作的時候數據庫中發生了什么。Derby提供了 derby.language.logQueryPlan這個參數。如果設置了這個參數,Derby將會把所有執行的查詢的查詢計劃(query plan)記錄在derby.log這個文件中(這個文件在derby.system.home文件夾中)。我們可以在啟動服務器之前通過合適的 derby.properties文件或者執行如下的java語句來設置該參數。 System.setProperty("derby.language.logQueryPlan", "true");


通過檢查查詢計劃,我們可以觀察Derby在查詢中是使用了索引還是進行了全表查詢,全表查詢是一個很耗時間的操作。

既然我們已經設置好了環境,我們可以開始我們的例子了。假設我們先前使用的表 tb1中有一個沒有索引的欄叫做owner。因為對查詢結果的排序通常是查詢性能低下的主要原因,我將介紹所有與排序有關的優化。現在,如果我們希望修改 先前的例子來根據這一欄的值來排序我們的結果,我們需要把我們的查詢語句改成如下的樣子: SELECT * FROM tbl ORDER BY owner


如果我們用這個查詢語句代替先前的語句,執行的時間將是先前的好多倍。盡管我們分頁(paginated)了所有的結果,并小心的設置了要獲取的行數,總的執行時間將會是8秒。

如果我們查看derby.log文件中查詢執行計劃,我們可以輕易的發現問題:Table Scan ResultSet for TBL at read committed isolation
level using instantaneous share row locking chosen
by the optimizer


這意味著Derby為了將記錄排序,是在整個表中執行了查找這個操作。那我們可以做些什么來改善這個情況呢?答案很簡單,在這一欄上創建一個索引。我們可以通過如下的SQL語句來做這件事: CREATE INDEX tbl_owner ON tbl(owner)


如果我們重復我們先前的例子,我們將得到一個和我們沒有做排序前的那個例子相似的結果(在我的機器上是不到1秒)。

同樣,如果你現在查詢derby.log,你將看到下面的信息(而不是和上面的一樣的):Index Scan ResultSet for TBL using index TBL_OWNER
at read committed isolation level using share row locking
chosen by the optimizer


這就意味著我們可以確保Derby使用了剛創建的索引來獲取合適的行。

使用合適的索引順序

我們已經看到了索引是如何幫助我們改善了排序某一欄數據時的性能。但是如果我們嘗試去反轉排序的順序的時候會發生什么呢?假設我們希望根據owner欄降序分類我們的數據。在這種情況下,我們原先的查詢就會變成如下的語句: SELECT * FROM tbl ORDER BY owner DESC


注意,我們增加了DESC這個關鍵字,該關鍵字將按降序來排序我們的結果。如果我們執行這個新修改過的查詢語句,將會發現整個執行的時間又增加到先前的8-9秒。并且,在日志文件中,你將會發現又是執行了全表掃描。

解決的方法就是為這一欄創建一個降序的索引。對于我們的owner欄,我們執行如下的SQL語句。 CREATE INDEX tbl_owner_desc ON tbl(owner desc)


現在我們對這一欄有兩個索引了(兩個順序),因此查詢性能又恢復到了可接受的范圍了。注意查詢日志中這一行:Index Scan ResultSet for TBL using index TBL_OWNER_DESC
at read committed isolation level using share row locking
chosen by the optimizer
這使我們確信我們使用了新建的索引。因此,如果你經常要對結果進行降序排序的話,你應該考慮創建一個合適的索引來獲取更高的性能。
轉自:
http://space.itpub.net/?uid-47598-action-viewspace-itemid-207379
posted on 2009-11-24 16:40 chatler 閱讀(1839) 評論(0)  編輯 收藏 引用 所屬分類: Database
<2009年10月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            狂野欧美一区| 欧美高清你懂得| 亚洲人精品午夜| 亚洲激情中文1区| 亚洲精品国久久99热| 在线观看欧美日韩国产| 加勒比av一区二区| 亚洲国产视频a| 亚洲品质自拍| 亚洲少妇在线| 久久久久久久欧美精品| 欧美成人精品高清在线播放| 亚洲国产精品热久久| 日韩视频在线一区二区三区| 亚洲综合色在线| 蜜桃精品一区二区三区| 欧美人与禽性xxxxx杂性| 国产精品视频一二| 91久久精品国产91久久性色| 欧美18av| 久久大逼视频| 亚洲裸体在线观看| 亚洲视频国产视频| 久久精品国产一区二区电影| 免费视频亚洲| 中文一区二区| 久久午夜精品| 国产精品久久久久久久久久久久 | 亚洲美女色禁图| 欧美一级片久久久久久久| 欧美激情一区二区三区不卡| 亚洲一区二区av电影| 欧美成人免费全部| 国产日本亚洲高清| 亚洲网友自拍| 亚洲国产高清在线| 欧美一区二区三区视频在线观看| 欧美精品一区二区视频 | 欧美一区国产一区| 欧美日韩黄视频| 伊人久久婷婷色综合98网| 亚洲字幕在线观看| 亚洲激情视频网站| 久久久久久久尹人综合网亚洲| 欧美性感一类影片在线播放| 亚洲另类在线视频| 欧美1区免费| 欧美在线视频观看免费网站| 国产精品人人做人人爽| 亚洲图片在线| 99re热这里只有精品视频| 欧美激情91| 亚洲另类春色国产| 亚洲人成网在线播放| 免费观看成人网| 亚洲成色777777女色窝| 久热精品视频在线观看| 久久精品2019中文字幕| 国产一区二区高清不卡| 久久噜噜噜精品国产亚洲综合| 欧美一乱一性一交一视频| 国产精品一区一区三区| 午夜精品久久久久久久白皮肤| 中日韩高清电影网| 国产精品v欧美精品v日本精品动漫| 亚洲视频国产视频| 亚洲免费一在线| 国产亚洲欧洲一区高清在线观看 | 久久久精品网| 欧美一区二区三区在线| 国产午夜精品视频免费不卡69堂| 先锋亚洲精品| 欧美亚洲一区在线| 1024亚洲| 亚洲精品美女久久久久| 欧美日韩黄色一区二区| 亚洲欧美日韩在线观看a三区| 亚洲一区在线免费| 极品少妇一区二区三区| 亚洲第一精品福利| 欧美日韩一区成人| 久久精品国产精品亚洲| 美女视频黄a大片欧美| 日韩一级欧洲| 亚洲欧美国产不卡| 亚洲国产精品va在线观看黑人| 亚洲国产美国国产综合一区二区| 欧美日韩视频| 久久久成人精品| 欧美精品日本| 久久久精品国产99久久精品芒果| 美女视频网站黄色亚洲| 亚洲一级二级在线| 久久国产66| 亚洲午夜高清视频| 久久精品视频一| 亚洲一区二区在线视频| 久久久久久9| 亚洲欧美日韩成人| 欧美www视频在线观看| 欧美一区二区三区免费看| 蜜桃伊人久久| 久久精品女人的天堂av| 欧美美女视频| 欧美xxxx在线观看| 国产美女精品视频| 亚洲精品一区二区三区av| 国产在线播放一区二区三区| 亚洲大胆人体在线| 国产婷婷色一区二区三区| 亚洲美女av电影| 亚洲福利一区| 欧美亚洲一区在线| 亚洲视频axxx| 欧美黑人多人双交| 蜜臀a∨国产成人精品| 国产欧美一级| 亚洲网站在线| 亚洲天堂激情| 欧美乱在线观看| 亚洲国产精品综合| 在线免费观看一区二区三区| 性欧美18~19sex高清播放| 亚洲一区亚洲二区| 欧美日韩一区二| 日韩视频在线永久播放| 日韩午夜av电影| 免费亚洲视频| 欧美激情亚洲自拍| 在线观看亚洲| 久久综合久久综合这里只有精品| 久久久久久久一区| 狠狠88综合久久久久综合网| 欧美在线观看你懂的| 亚洲欧美日韩直播| 亚洲欧美精品suv| 亚洲深夜激情| 亚洲人成网站777色婷婷| 久久大逼视频| 久久久99久久精品女同性| 欧美性事在线| 亚洲一区二区免费看| 亚洲女人天堂av| 欧美午夜精品久久久久免费视| 欧美激情一区二区三区在线视频| 黄色一区二区在线观看| 欧美一区二区在线看| 久久精品视频播放| 国语自产偷拍精品视频偷| 亚洲欧美日韩中文在线制服| 性做久久久久久久免费看| 国产欧美日韩综合一区在线观看| 性欧美大战久久久久久久免费观看 | 亚欧美中日韩视频| 久久av一区二区三区漫画| 国产性色一区二区| 久久久久久有精品国产| 亚洲国产视频直播| 一本色道**综合亚洲精品蜜桃冫| 国产精品va在线| 亚洲欧美一区二区三区久久 | 欧美激情网友自拍| 亚洲精品欧洲精品| 亚洲在线中文字幕| 国产一区二区你懂的| 免费中文日韩| 亚洲一区二区三区影院| 久久噜噜噜精品国产亚洲综合| 亚洲国产另类精品专区| 欧美日韩综合| 欧美一区二视频在线免费观看| 免费成人高清| 午夜视黄欧洲亚洲| 最新日韩精品| 国产色爱av资源综合区| 欧美大片在线观看| 欧美一区二区观看视频| 亚洲欧洲日本在线| 久久久久久黄| 在线一区视频| 亚洲成色www8888| 国产精品美腿一区在线看| 久久嫩草精品久久久久| 亚洲私人影院在线观看| 欧美激情第4页| 久久久久久9| 亚洲自拍偷拍网址| 亚洲人成亚洲人成在线观看图片 | 夜夜嗨av一区二区三区免费区| 国产一区二区三区黄| 国产精品videossex久久发布| 蜜臀久久99精品久久久久久9| 亚洲一区二区三区影院| 亚洲精品国产拍免费91在线| 鲁大师影院一区二区三区| 久久亚洲春色中文字幕| 欧美一区二区私人影院日本| 91久久精品久久国产性色也91| 久久国产精品黑丝| 亚洲欧美日韩综合一区|