找到时间戳和标识不按顺序排列的行的有效方法是什么?

时间:2010-01-29 22:17:02

标签: sql sql-server oracle transactions query-optimization

背景

我有一个MS SQL应用程序,每小时从我们的Oracle计费数据库中读取数据,寻找新的付款。它通过存储基于每次运行时找到的最新时间戳的CRT_DTTM的时间戳来实现此目的。

e.g。

SELECT *
FROM V_TRANS
WHERE TRANS_CLS = 'P'
AND CRT_DTTM > TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS')

返回此结果后,MAX(CRT_DTTM)将存储为下一小时运行的起始时间戳。

似乎正在发生的事情是,有时在Oracle端运行的事务是在我运行查询的同时将数据插入表中。这些行似乎没有按照它们获得的时间戳顺序插入。这意味着我的MAX(CRT_DTTM)大于我的查询完成后插入的一些行。我错过了付款信息,而且我的系统不平衡。

我相信我可以通过简单地修改上面的SQL语句来解决这个问题:

...
AND CRT_DTTM < SYSDATE - INTERVAL '10' MINUTE

问题:

我想知道的是,是否有办法检查已经插入到表中的行,以找到那些带有时间戳的身份无序的口袋:

database sequence vs timestamp http://i46.tinypic.com/r70sk0.png

我希望在这种情况下找到大量数据,以便了解10分钟是否足够长,以便暂时停止查看时间戳。

SELECT *
FROM V_TRANS t1
JOIN V_TRANS t2
    ON t1.trans_id < t2.trans_id
        AND t2.crt_dttm < t1.crt_dttm
WHERE t1.TRANS_CLS = 'P'
    AND t1.CRT_DTTM > TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS')
    -- Only look at an interval of one day
    AND t1.CRT_DTTM < TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS') + 1

或许我忽略了一些基本的事务隔离级别设置?我是通过OPENQUERY()

的链接服务器运行的

3 个答案:

答案 0 :(得分:2)

SELECT
  *
FROM (
        SELECT
          t1.*,
          RANK() OVER (ORDER BY trans_id) AS trans_id_rank,
          -- Ordering by trans_id after CRT_DTTM to cater for transactions within the same second
          RANK() OVER (ORDER BY CRT_DTTM, trans_id) AS CRT_DTTM_rank
        FROM V_TRANS t1) t
WHERE trans_id_rank <> CRT_DTTM_rank

答案 1 :(得分:1)

“这些行似乎没有按照他们获得的时间戳的顺序插入。” 更有可能的是,它们没有按时间戳顺序进行COMMITED,因此在运行查询时它们已被插入但未提交。

查看Oracle DBA是否会为您提供V $ TRANSACTION的授权。然后,您可以查看任何未结交易的开始时间,交易时间等。 此外,如果Oracle数据库是RAC,则很可能序列号(最接近的Oracle必须标识列)也不是有序的。 RAC中的每个节点都有自己的缓存来减少争用。

在11gR2中,他们引入了WAITING_ON_PENDING_DML来满足这种情况。

答案 2 :(得分:0)

select t1.id, t2.id, t1.timestamp - t2.timestamp
from table t1
join table t2 on t1.id = t2.id - 1
where t1.timestamp < t2.timestamp

编辑:

我写了这个答案,然后意识到它或多或少是你已经拥有的相同查询。所以我不能理解你的问题。

我的查询将“...检查已经插入到表格中的行,以找到那些带有时间戳的身份无序的口袋”,我认为这是你的问题。

顺便说一句,如果您只是想查找时间戳最大的跳跃,您可以使用:

select max(t2.timestamp - t1.timestamp)
from table t1
join table t2 on t1.id = t2.id - 1;

如果我误解了你的问题,请让我知道我错过了什么。