現(xiàn)在參與一個項目的開發(fā),需要用java查詢mongodb數(shù)據(jù)庫,在這里分頁用的skip sort 和limit結(jié)合,查詢語句如下(已經(jīng)在相關(guān)字段建立索引)
?
DBCursor cursor = collection.find(query).skip((skip - 1) * PAGESIZE).sort(new BasicDBObject("starttime", -1)).limit(PAGESIZE);//PAGESIZE=10
由于分頁,這里需獲取符合條件的總數(shù) 語句如下
?
int count = cursor.count()
根據(jù)count和PAGESIZE的兩個數(shù)據(jù)來分頁。由于帶條件的count()方法執(zhí)行起來特別耗時,我用二百萬的數(shù)據(jù)測試了一下,cursor.count()就耗時6.5s多,mongodb權(quán)威指南這不書也指出count()方法隨著查詢條件越多,執(zhí)行速度越慢。
現(xiàn)在問題出來了,現(xiàn)在模擬一下操作
1)點擊查詢執(zhí)行查詢方法queryLists()(這是我代碼中的方法名)并執(zhí)行耗時的count()方法獲取符合條件的數(shù)量,進(jìn)行分頁
2)點擊下一頁或者點擊某一頁時,同樣執(zhí)行queryLists()方法,同樣也需要執(zhí)行該方法體中的count()方法,這樣count方法又耗去一部分時間
顯然用戶體驗不是很好,每次點擊查詢時就很耗時了,點擊下一頁或者某一頁時同樣還得等待,這樣的話誰都受不了
下面是我的優(yōu)化方案
1)設(shè)置一個變量clickQuery,當(dāng)用戶點擊查詢按鈕時 clickQuer賦值為0.當(dāng)點擊下一頁或者上一頁或者跳轉(zhuǎn)頁面時clickQuery=1.
???? 也就是說用clickQuery來判斷用戶是否點擊查詢按鈕
2)既然點擊查詢時已經(jīng)獲取了count,何必再點擊下一頁時在執(zhí)行cursor.count()方法呢?所以我的做法就是把點擊查詢的時候獲取的count保存起來
??? 當(dāng)用戶點擊下一頁的時候,直接讀取已經(jīng)保存的count,而不是執(zhí)行耗時的cursor.count()方法
方法優(yōu)點:
????? 點擊下一頁或者某一頁或者跳轉(zhuǎn)頁面時,由于已經(jīng)保存過查詢時的count,所以速度很快
方法缺點:
??? 用戶點擊查詢按鈕時,因為要執(zhí)行cursor.count方法,所以還是很慢。
代碼實現(xiàn)如下
?
int count = 0;
if (click.equals("0")) {// 如果點擊查詢
count = cursor.count();//獲取符合條件的數(shù)量
// 序列化,保存count2
Seria.serializable(new BtnClick(count), Seria.ACTIVITY_COUNT_FILE);
System.out.println("點擊查詢");//Seria是我自己定義的一個類,來序列化數(shù)據(jù)
} else {// 如果點擊下一頁或者跳轉(zhuǎn)頁
// 讀取序列化信息
BtnClick btnClick = Seria.reverseSer(Seria.ACTIVITY_COUNT_FILE);
count= btnClick.getCount();
System.out.println("點擊下一頁");
}
///分頁處理略
?
/**
* 序列化
*/
public static void serializable(BtnClick btnClick,String file) {
try {
File serFile = new File(file);
// 判斷序列化文件是否存在, 不存在則創(chuàng)建
if (!serFile.exists())
serFile.createNewFile();
//打開serFile的輸出流
FileOutputStream fos = new FileOutputStream(serFile);
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 將上下文對象寫到序列化文件中
oos.writeObject(btnClick);
oos.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 反序列化
*/
public static BtnClick reverseSer(String file) {
File serFile = new File(file);
BtnClick btnClick = null;
if (!serFile.exists())
return null;
try {
// 得到文件輸入流
FileInputStream fis = new FileInputStream(serFile);
ObjectInputStream ois = new ObjectInputStream(fis);
// 設(shè)置ContextHolder的DownloadContext
btnClick = (BtnClick) ois.readObject();
ois.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return btnClick;
}
?
我的問題:因為用skip方法查詢大量數(shù)據(jù)的時候速度慢,不知道有什么方法可以優(yōu)化一下,mongodb權(quán)威指南的那個方法,只適合一頁一頁的調(diào)整而不適合跨頁跳轉(zhuǎn),所以大家如果有好的查詢方案,可以和小弟在此說一下,謝謝。
?
同樣以上方法如有不當(dāng)之處,歡迎批評指正
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

