MySQL:将大表分成分区或单独的表?

时间:2017-09-20 08:32:52

标签: mysql database partitioning large-data

我有一个超过20个表的MySQL数据库,但其中一个非常大,因为它收集来自不同传感器的测量数据。它在磁盘上的大小约为145 GB,包含超过10亿条记录。所有这些数据也被复制到另一个MySQL服务器。

我想将数据分成较小的“分片”,所以我的问题是以下哪种解决方案会更好。我将使用记录的“时间戳”将数据除以年份。几乎所有在此表上执行的SELECT查询都包含查询“where”部分中的“timestamp”字段。

以下是我无法决定的解决方案:

  1. 使用MySQL分区并按年划分数据(例如partition1 - 2010,partition2 - 2011等)
  2. 创建单独的表格并按年划分数据(例如measurement_2010,measuring_2011等表格)
  3. 还有其他(较新的)可能的选项,我不知道吗?

    我知道在第一种情况下,MySQL本身会从“分片”中获取数据,在第二种情况下,我必须为它编写一种包装并自行完成。对于第二种情况,是否有其他方法可以使所有单独的表被视为“一个大表”来从中获取数据?

    我知道这个问题在过去已经被问过了,但是也许有人提出了一些新的解决方案(我不知道)或者现在已经改变了最佳实践解决方案。 :)

    非常感谢你的帮助。

    编辑:

    架构与此类似:

    device_id (INT)
    timestamp (DATETIME)
    sensor_1_temp (FLOAT)
    sensor_2_temp (FLOAT)
    etc. (30 more for instance)
    

    所有传感器温度均在每分钟写入一次。请注意,连续写入大约30个不同的传感器测量值。此数据主要用于显示图表和其他一些统计目的。

2 个答案:

答案 0 :(得分:1)

好吧,如果你希望得到一个新的答案,这意味着你可能已经阅读了我的答案,而且我听起来像是一个破纪录。有关分区可以帮助提高性能的少数用例,请参阅Partitioning blog。你的听起来像4个案例中的任何一个。

收缩device_idINT是4个字节;你真的拥有数百万台设备吗? TINYINT UNSIGNED是1个字节,范围是0..255。 SMALLINT UNSIGNED是2个字节,范围是0..64K。这会使桌子缩小一点。

如果真正的问题是关于如何管理如此多的数据,那么请在框外思考"。请继续阅读。

绘图...你在绘制什么日期范围?

  • ' last'小时/天/周/月/年?
  • 任意小时/日/周/月/年?
  • 任意范围,与日/周/月/年边界无关?

你在画什么?

  • 一天的平均价值?
  • 一天的最大/分钟?
  • 烛台(等)一天或一周或其他什么?

无论如何,您都应该使用数据构建(并逐步维护)摘要表。一行将包含一小时的摘要信息。我建议

CREATE TABLE Summary (
    device_id SMALLINT UNSIGNED NOT NULL,
    sensor_id TINYINT UNSIGNED NOT NULL,
    hr TIMESTAMP NOT NULL,
    avg_val FLOAT NOT NULL,
    min_val FLOAT NOT NULL,
    max_val FLOAT NOT NULL
    PRIMARY KEY (device_id, sensor_id, hr)
) ENGINE=InnoDB;

一个Summary表可能是9GB(对于当前数据量)。

SELECT hr,
       avg_val,
       min_val,
       max_val
    FROM Summary
    WHERE device_id = ?
      AND sensor_id = ?
      AND hr >= ?
      AND hr  < ? + INTERVAL 20 DAY;

会给你480小时的hi / lo / avg值;足以图?从汇总表中抓取480行比从原始数据表中抓取60 * 480行快得多。

获取一年的类似数据可能会扼杀图形包,因此可能值得建立摘要摘要 - 以一天的分辨率。它大概是0.4GB。

构建Summary表有几种不同的方法;在你思考了它的美丽之后我们可以讨论这个问题并阅读Summary tables blog。可能是收集一小时的数据,然后增加摘要表,是最好的方法。这有点像所讨论的触发器my Staging table blog

而且,如果你有每小时的摘要,你真的需要逐分钟的数据吗?考虑扔掉它。或者,也许是一个月之后的数据。这导致使用分区,但仅为了删除旧数据的好处,如&#34;案例1和#34; Partitioning blog。也就是说,您每天都会使用DROPREORGANIZE进行每日分区,以转移&#34;事实&#34;表。这将导致减少145GB的占用空间,但不会丢失太多数据。新的足迹:大约12GB(每小时摘要+最近30天和#39;每分钟详细信息)

PS:Summary Table blog显示了如何获得标准偏差。

答案 1 :(得分:0)

你没有多说你如何使用/查询数据或模式是什么样的,但我试着做些什么。

  1. 您可以分割表格的一个方面是基于实体 (不同的传感器是不同的实体)。如果这很有用 不同的传感器需要不同的列所以你不需要 强制他们进入一个适合所有人的模式(最不常见 多)。虽然添加或移除传感器并不好 动态,因为您必须在运行时添加表。
  2. 另一种方法是根据时间拆分表格。这是 如果一段时间后数据可以“历史化”并且不用于 实际的业务逻辑,但出于统计目的。
  3. 两种方法也可以组合使用。此外,请确保根据您的查询需求正确索引表格。

    我强烈反对任何经常需要在一段时间后或类似情况下添加表格的方法。一如既往,在出现性能问题之前,我不会拆分任何东西。

    编辑:
    我会清楚地将表重组为跟随而不是完全拆分:

    device_id (INT)
    timestamp (DATETIME)
    sensor_id (INT) -- could be unique or not. if sensor_id is not unique make a 
                    -- composite key from device_id and sensor_id given that you 
                    -- need it for queries
    sensor_temp (FLOAT)
    

    如果数据增长很快并且您希望很快就会生成数TB的数据,那么使用NoSQL方法会更好。但那是一个不同的故事。