今天幫同事解決了一個問題,記錄一下,幫助有需要的人。
一、問題解決經過
事情的經過是這樣的,下午我在敲代碼的時候,一個同事悄悄走到我身邊,問我有沒有用沒用過Oracle,這下我蒙了,難道我在他們眼中這么弱嗎?不過我還是弱弱的問了一句咋了,他說碰到一個奇怪的現象,說他用jdbc查詢Oracle,然后循環取數據要30秒,我問怎么可能,他說是真的,就1000條數據,我當然不信,就說帶我去看。
然后我走過去,發現他旁邊還坐了一個人,我猜也在幫忙解決問題,只不過沒有解決而已,我讓他給我看看代碼,我看了一眼,發現很簡單,如下(只是示例代碼,真實代碼不便貼出):
Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); long start=System.currentTimeMillis(); while(rs.next()){ //一系列操作 } System.out.println(System.currentTimeMillis()-start); =========控制台輸出========== 大約就是30秒以上
我一看,這不是標准的jdbc操作嗎,我都寫了800遍了,怎么可能會有問題,有問題也只能是SQL問題,於是我說給我看看你的SQL,我覺得你寫的SQL有問題,結果他說不可能,SQL沒有問題,而且我剛剛打斷點一步一般走下去都很快,就是next()方法耗時30多秒的,旁邊那位依然也說不可能是SQL的問題,SQL都看了,然后我又說了一遍,給我看看你寫的SQL,結果還是說SQL肯定沒問題,旁邊那位甚至說出了讓我驚訝的話,他說是不是ResultSet 的next方法有問題,你快去網上找找有沒有其他的替代方法。
此時我心中一萬只草泥馬奔騰而過,我看過一些源碼,而且知道操作數據庫的底層都是封裝的它們,旁邊這位不僅不解決問題,還打算掩埋問題繞彎路,我想說你把我叫過來解決問題,能不能聽我的,不過我沒有這么說,因為他們兩個都是我的領導,要不是喊我過來的那個我和他關系很好,我早就回去不管了。
不過在我的再三請求下還是給我看了SQL,我一看很長,我就說拿到PL/SQL中執行一下,結果又來否定我,說我都執行過了很快的,旁邊那位依然大聲說怎么可能是SQL問題呢,以前就用過了,我只能說我心好累,最終放到PL/SQL中執行了,結果確實是兩三秒顯示出來,他們就說你看。
我什么也沒說,大家應該都知道PL/SQL執行后只會顯示前多少條數據,只有點向下的箭頭才會顯示所有的數據,我就讓他顯示所有的數據,因為只有1000條我想是很快的,確實剩下的飛快的顯示完,但是當顯示完1000條數據以后,執行並沒有終止,直到30多秒過去以后,才顯示執行完成,也就是說查詢出需要的1000條數據后,查詢依然進行只是沒有輸出結果。
我說你SQL寫的有問題,結果在這種情況下,他居然還說,那剛剛那條語句怎么飛快的執行完了呢:
ResultSet rs = stmt.executeQuery(sql);
說這條執行完了,不就把所有的結果都帶回來了嗎,說實話我沒有深入了解過,不過我猜應該是沒有帶回來,我讓他測試一下,取所有數據大約5W條,ResultSet 依然很迅速的獲取到,但是按常理是不會這么快的,結合剛才的現象猜測,ResultSet 並沒有帶回來結果集。
然后我又看了一遍他寫的SQL,看出了問題,分頁寫錯了,我說你改好應該就沒有問題了。
二、收獲總結
2.1 我的收獲
幫別人解決問題還是有收獲的,首先可以肯定的事是ResultSet.next() 效率低下是錯覺,真正效率低下的是寫出SQL的執行速度,同樣ResultSet只是代表着結果集,而不表示它就是整個結果集的數據,具體源碼等我有空的時候會研究並貼出。
2.2 我想說的話
當出現奇怪的問題的時候,不要這么做:
- 大量重復測試
- 懷疑框架,懷疑Java,懷疑人生
這兩條是很重要的,大量重復測試是大忌,浪費時間而且還容易掩蓋錯誤,一遍遍看着結果露出不可置信的眼神,第二條就是懷疑Java是不是有缺陷,框架是不是有bug,當然不可否認任何東西都不是完美的,但是相比較而言,還是首先懷疑自己比較好。把自己理所當然覺得沒問題的步驟好好看一遍,也許原因就在其中。