当您说“...或查询每个值的最后一个时间戳”时,您的意思是这样吗?
select max(timestamp) from T where value = ?
如果您有数百万条记录,并且上面是您的意思(即 value 在 WHERE 子句中单独存在),那么您需要在 value 列上建立索引,否则您必须做一个完整的表扫描。但是,如果查询在 WHERE 子句中总是有 [timestamp] 列,那么如果时间戳上有索引,则不需要在 [value] 列上创建索引。
如果您的用户将在时间戳列单独出现在 WHERE 子句中的情况下发出查询,则您需要时间戳列上的索引:
select * from T where timestamp > x and timestamp < y
您可以索引所有三列,但要确保写入不会因为索引开销而减慢。
当您拥有一个非常大的数据库时,经验法则是每个查询都应该能够使用索引,这样您就可以避免全表扫描。
编辑:
在您澄清后添加一些补充说明。
我想知道你是如何知道 id 的? [id] 可能是产品代码吗?
如果没有很多不同的产品代码,即如果它是一个低基数索引,则 id 上的单个简单索引可能无法很好地扩展。树的重新平衡可能会减慢每 x 毫秒发生的批量插入。 (id,timestamp) 上的复合索引比简单索引要好。
如果您很少需要对多个产品进行排序,但最常基于单个产品代码进行选择,那么使用散列键稀疏表而不是 b 树的非传统 DBMS 可能是非常可行的甚至是您的绝佳选择。在这样的数据库中,给定键的所有记录都可以在同一组连续的“页面”上找到;散列算法查看键并返回将找到记录的页码。由于没有索引,因此无需重新平衡索引,因此您完全避免了相关的缩放问题。
然而,虽然散列文件数据库在基于键值的低开销几乎即时检索方面表现出色,但它们在对属性上的大量记录进行排序方面往往表现不佳,因为数据没有以任何有意义的物理方式存储秩序,收集记录可能会涉及很多颠簸。在您的情况下,时间戳就是该属性。如果我站在你的立场上,我会根据 id 的基数做出决定:在一百万条记录的数据集中,会找到多少个 DISTINCT id?
由于该网站不允许我添加另一个答案,因此还有另一个编辑:
最简单的方法是创建两个表,一个包含正在进行的历史记录,始终插入新值,另一个仅包含 250 条记录,每部分一条,其中最新值覆盖/替换前一个值。
Update latest
set value = x
where id = ?