【问题标题】:Organizing lots of timestamped values in a DB (sql / nosql)在数据库中组织大量带时间戳的值(sql / nosql)
【发布时间】:2010-11-09 10:36:11
【问题描述】:

我有一个设备要轮询许多不同的字段,每 x 毫秒 设备返回一个 ID 和值列表,我需要将它们与时间戳一起存储在各种数据库中。

系统用户需要能够查询此数据库以获取历史日志以创建图表,或查询每个值的最后一个时间戳。

一个简单的方法是定义一个 MySQL 表

id,value_id,timestamp,value

并让用户选择

Select value form t where value_id=x order by timestamp desc limit 1

然后用时间戳和 id 上的索引将所有内容推送到那里,但我的问题是设计架构的最佳方法性能/大小是什么?还是使用nosql?任何人都可以评论可能的设计权衡。这样的设计会扩展到数百万条记录吗?

【问题讨论】:

    标签: sql mysql nosql


    【解决方案1】:

    当您说“...或查询每个值的最后一个时间戳”时,您的意思是这样吗?

        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 = ?
    

    【讨论】:

    • 我在 id 上进行选择,需要将值取出,添加了我对选择如何工作的思考
    • 大约有 250 个 DISTINCT IDS
    【解决方案2】:

    你可以选择

    • 索引(复合;涵盖 value_id、timestamp 和 value 或它们的某种组合):您应该使用不同的索引测试性能;复合和非复合,还要注意有很多明显不同的方法可以获得“每组最大值”(搜索,尤其是带有变量的 mysql 版本)

    • 触发器 - 您可以使用触发器来维护另一个表中的最大行值(进一步选择的最佳性能;这是多余的,可以保存在内存中)

    • 惰性统计信息/触发器,因为您的数据库经常更新,如果您定期更新统计信息,则可以节省周期(如果您可以允许统计信息为 y 秒,并且如果您每秒轮询 1000 / x 次,那么您可能会节省 y * 100 / x 次潜在更新;这可能很明显,尤其是在可扩展性方面)

    如果您正在寻找最后一点的性能,以上是正确的,如果不是保持简单。

    【讨论】:

    • 您是否需要维护每个部分的被取代值的历史记录?还是您真的只对最近的值感兴趣?我已经更新了我的答案,以展示你如何能够非常有效地做到这两点。
    • 我都需要,感谢您的出色回答!
    • “搜索so,尤其是带变量的mysql版本”是什么意思?
    • search so 意味着搜索堆栈溢出:获取包含某个聚合值(最小值、最大值等)的行是 SQL 标记最常见的问题之一。并且有一些(本质上不同的)方法可以在 SQL 中实现。
    猜你喜欢
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多