今天在开发的时候用了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!!!!!!!!!!!!