今天在開發的時候用了oracle的分頁,語句如下(ibatis)
SELECT *
FROM (SELECT t1.*,rownum as linenum
FROM (SELECT
A.MEMBERID memberID,
A.LOGNAME logName,
A.STATUS status,
A.UPDATETIME updateTime,
A.OPERATORNAME operatorName
FROM BD_BAOYANG_LIST A
WHERE
<![CDATA[
A.TYPE='BUY'
]]>
<dynamic>
<isEqual property="status" compareValue="1" prepend="and">
A.STATUS=1
</isEqual>
<isEqual property="status" compareValue="-1" prepend="and">
<![CDATA[
A.STATUS<>1
]]>
</isEqual>
<isNotEmpty property="memberID" prepend="and">
A.MEMBERID = #memberID#
</isNotEmpty>
<isNotEmpty property="logName" prepend="and">
A.LOGNAME = #logName#
</isNotEmpty>
<isNotEmpty property="startTime" prepend="and">
<![CDATA[
A.UPDATETIME >= cast(#startTime# as DATE)
]]>
</isNotEmpty>
<isNotEmpty property="endTime" prepend="and">
<![CDATA[
A.UPDATETIME < cast(#endTime# as DATE)+1
]]>
</isNotEmpty>
</dynamic>
<![CDATA[
ORDER BY A.UPDATETIME DESC) t1
WHERE ROWNUM <= #endRow#) t2
WHERE linenum >= #startRow#
]]>
在運行后發現查詢出來的結果總條數和數據庫里的記錄數量是一致的,但是出現了數據重復現象,也就是說有些數據被重復的記錄替換了。
一開始以為是Java程序邏輯問題,經過認真的排查,排除了程序的問題。
仔細看了一下數據庫里的數據,發現UPDATETIME這一列的數據格式是yyyy-MM-dd沒有小時-分-秒的。這樣該列的數據就出現了重復現象,這時我產生了疑問:難道oracle在對數據進行排序的時候對重復的排序條件是不能保證順序的不變性?
帶著這個問題我查詢了oarcle的相關資料。
經過查詢資料發現,oracle在對小量數據查詢的時候會將數據放到緩存內進行排序,當數據量達到一定程度時會將數據在磁盤排序,而磁盤排序時當遇到排序條件相同的情況下,會根據該條記錄的更新時間進行排序(我想可能是ROWID

),但是如果放到內存排序的話如果不指定排序條件就不會走更新時間,因此我在上面的程序ORDER BY A.UPDATETIME DESC 修改成ORDER BY A.UPDATETIME DESC,A.ROWID DESC這樣就解決了問題,但是這樣解決的方式十分的不優雅,第一:這樣UPDATETIME上建立的索引就不再起作用,第二:當該表數據量很大的時候,就會導致查詢非常耗時,但是業務要求又必須按照UPDATETIME來進行排序,因此建議如果表的數據量很大就應該將該時間字段 提供 小時/分鐘/秒鐘
OVER!!!!!!!!!!!!