处理MySQL中的整数溢出ORDER BY

时间:2016-08-15 11:07:28

标签: mysql

我知道这个问题可以通过适当的设计(如BIGINT ID或小数时间戳)完全避免,但这些都超出了我的能力。

计算机使用整数ID和第二精度时间戳将数据提供到MySQL数据库中。数据每90ms被馈送一次,ID相应地增加,即从1到91增加到181等。由于这种增量每秒发生几次,所以存在具有相同时间戳的不同ID。此外,ID字段只是一个无符号的smallint,因此当它达到65536时会出现溢出。

我确实需要按时间排序的数据,所以很简单

ORDER BY timestamp ASC, ID ASC 

适用于时间戳覆盖的第二个内没有溢出的情况。不幸的是,如果出现溢出,ID 42,132和222将在65308,65398和65488之前排序。

有没有办法做类似

的事情
ORDER BY
    timestamp ASC, 
    If((min(ID)<10000) and (max(ID)>60000), If(ID<10000, ID+65536, ID), ID)

以某种方式指定min()max()应适用的范围?

编辑1:数据是批量添加的,因此auto_increment列(我必须将记录分开,即使是多余的)也不一定反映正确的时间顺序。< / p>

编辑2:请参见顶部的斜体字。

1 个答案:

答案 0 :(得分:0)

您有多少数据库设计?显然,您无法更改主键字段的宽度。如果您可以更改时间戳列的精度,则可以包含fractions of a second

另一种方法是向数据库发出定时SQL语句,每隔n秒重置一次AUTO_INCREMENT计数器,以便时间戳间隔内不会发生溢出。但是,显然需要将时间精确到90 ms。

如果所有其他方法都失败了,请在触发器的帮助下将数据复制到另一个表中,并在执行此操作时计算订单条件。对于纯SQL,这可能会很慢,但是一个简单的脚本可能会起到作用。

编辑:我已经快速重新创建了您的架构,并使用一些测试数据填充它以提出这个查询的野兽,并采用相同的假设,重叠区域只能说谎介于10,000和60,000之间:

SELECT *, (SELECT IF(COUNT(*) > 0, 1, 0) FROM test t WHERE t.timestamp = test.timestamp AND t.id NOT BETWEEN 10000 AND 60000) AS has_overlap FROM test ORDER BY timestamp ASC, IF(has_overlap AND id < 10000, id + 65536, id)

现在你只需要测试它的性能,因为子查询可能会杀了你。如果是这种情况,请在进行有序的SELECT查询之前预先计算它。