我有一个设备,我每隔x毫秒轮询很多不同的字段 设备返回一个id和值列表,我需要在DB中存储时间戳。
系统用户需要能够查询此数据库以查找历史日志以创建图表,或查询每个值的最后时间戳。
一种简单的方法是使用
定义MySQL表id,value_id,timestamp,value
让用户选择
Select value form t where value_id=x order by timestamp desc limit 1
然后用时间戳和id上的索引来推送所有内容,但我的问题是设计架构的最佳方法性能/大小是什么?还是使用nosql?任何人都可以评论可能的设计权衡。这样的设计会有数百万条记录吗?
答案 0 :(得分:1)
当您说“...或查询每个值的最后一个时间戳”时,您的想法是什么?
select max(timestamp) from T where value = ?
如果你有数百万条记录,并且上面是你的意思(即WHERE子句中的值是唯一的),那么你需要在value列上有一个索引,否则你必须做一个完整的表扫描。但是如果查询总是在WHERE子句中有[timestamp]列,那么如果时间戳上有索引,则不需要[value]列的索引。
如果您的用户将在WHERE子句中单独出现timestamp列的查询时,您需要timestamp列的索引:
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 = ?
答案 1 :(得分:1)
您可以选择
索引(复合;覆盖value_id,时间戳和值,或它们的某种组合):您应该使用不同的索引来测试性能;复合和非复合,也要注意有很多显着不同的方法来获得'每组最大'(搜索,特别是带变量的mysql版本)
触发器 - 您可以使用触发器来维护另一个表中的最大行值(进一步选择的最佳性能;这是多余的,可以保留在内存中)
懒惰的统计信息/触发器,因为您的数据库经常更新,如果您定期更新统计信息,您可以保存周期(如果您可以允许统计信息为y秒,如果您每秒轮询1000次/次) ,那么你可能会节省y * 100 / x的潜在更新;这很明显,特别是在可扩展性方面)
如果您正在寻找性能的最后一点,如果不是保持简单,则上述情况属实。