【问题标题】:Partiton mysql table by column timestamp按列时间戳对mysql表进行分区
【发布时间】:2018-10-19 09:23:50
【问题描述】:

我正在尝试对我的表 MySQL innoDB 进行分区。现在位置表中大约有 200 万行(并且一直在增长)历史数据行。我必须定期删除旧的数据集 我使用 MySQL 5.7.22 社区服务器。

CREATE TABLE `geo_data` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `ID_DISP` bigint(20) DEFAULT NULL,
  `SYS_TIMESTAMP` datetime DEFAULT NULL,
  `DATA_TIMESTAMP` bigint(20) DEFAULT NULL,
  `X` double DEFAULT NULL,
  `Y` double DEFAULT NULL,
  `SPEED` bigint(20) DEFAULT NULL,
  `HEADING` bigint(20) DEFAULT NULL,
  `ID_DATA_TYPE` bigint(20) DEFAULT NULL,
  `PROCESSED` bigint(20) DEFAULT NULL,
  `ALTITUDE` bigint(20) DEFAULT NULL,
  `ID_UNIT` bigint(20) DEFAULT NULL,
  `ID_DRIVER` bigint(20) DEFAULT NULL,
  UNIQUE KEY `part_id` (`ID`,`DATA_TIMESTAMP`,`ID_DISP`),
  KEY `Index_idDisp_dataTS_type` (`ID_DISP`,`DATA_TIMESTAMP`,`ID_DATA_TYPE`),
  KEY `Index_idDisp_dataTS` (`ID_DISP`,`DATA_TIMESTAMP`),
  KEY `Index_TS` (`DATA_TIMESTAMP`),
  KEY `idx_sysTS_idDisp` (`ID_DISP`,`SYS_TIMESTAMP`),
  KEY `idx_clab_geo_data_ID_UNIT_DATA_TIMESTAMP_ID_DATA_TYPE` (`ID_UNIT`,`DATA_TIMESTAMP`,`ID_DATA_TYPE`),
  KEY `idx_idUnit_dataTS` (`ID_UNIT`,`DATA_TIMESTAMP`),
  KEY `idx_clab_geo_data_ID_DRIVER_DATA_TIMESTAMP_ID_DATA_TYPE` (`ID_DRIVER`,`DATA_TIMESTAMP`,`ID_DATA_TYPE`)
) ENGINE=InnoDB AUTO_INCREMENT=584390 DEFAULT CHARSET=latin1;

我必须按DATA_TIMESTAMP(格式时间戳日期gps)进行分区。

ALTER TABLE geo_data
PARTITION BY RANGE (year(from_unixtime(data_timestamp)))
(
   PARTITION p2018 VALUES LESS THAN ('2018'),
   PARTITION p2019 VALUES LESS THAN ('2019'),
   PARTITION pmax VALUES LESS THAN MAXVALUE
);

错误代码:1697。分区“p2018”的 VALUES 值必须为 INT 类型

我该怎么办?

我想稍后通过 ID_DISP 添加一个子分区范围。我该怎么办?

提前致谢!

【问题讨论】:

    标签: mysql partition database-partitioning


    【解决方案1】:

    由于data_timestamp 实际上是BIGINT,因此不允许您使用日期函数。似乎有两个错误,这可能会解决它们:

    ALTER TABLE geo_data
    PARTITION BY RANGE (data_timestamp)
    (
       PARTITION p2018 VALUES LESS THAN (UNIX_TIMESTAMP('2018-01-01') * 1000),
       PARTITION p2019 VALUES LESS THAN (UNIX_TIMESTAMP('2019-01-01') * 1000),
       PARTITION pmax VALUES LESS THAN MAXVALUE
    );
    

    我假设你的 data_timestamp 真的是毫秒,一个 la Java?如果没有,请决定如何处理* 1000

    SUBPARTITIONs 没用;不要打扰他们。如果您真的想按月或季度进行分区,那么只需在 PARTITION 级别进行。

    建议:分区不要超过 50 个。

    你有多少“司机”?我怀疑你没有万亿。所以,不要盲目地使用BIGINT 作为id。每个占用 8 个字节。例如,SMALLINT UNSIGNED 将只占用 2 个字节并允许 64K 驱动程序(等)。

    如果XY 是纬度和经度,那么这样命名可能更清楚。 Here 是要使用的数据类型,而不是 8 字节 DOUBLE,具体取决于您拥有(和需要)的分辨率。 4 字节的FLOATs 对于车辆来说可能已经足够了。

    该表有几个冗余索引;折腾他们。另外,请注意,当您拥有INDEX(a,b,c) 时,同时拥有INDEX(a,b) 是多余的。

    另请参阅我的 discussion 关于分区,尤其是与时间序列相关的内容,例如您的。

    嗯...我想知道SPEED 的 63 位精度是否可以让您在它们以光速行驶时记录下来?

    另外一点:在 2019 年初之前不要创建p2019。你有pmax,以防你犯错并且未能及时添​​加该分区。而我在讨论中提到的REORGANIZE PARTITION 涵盖了如何从这种愚蠢中恢复过来。

    【讨论】:

      【解决方案2】:

      更新:

      您似乎不能在PARTITION BY RANGE 查询中使用from_unixtime,因为哈希分区必须基于整数表达式。更多信息see this answer

      它期待 INT 而不是 STRING(根据错误消息),所以试试:

      ALTER TABLE geo_data
      PARTITION BY RANGE (year(from_unixtime(data_timestamp)))
      (
         PARTITION p2018 VALUES LESS THAN (2018),
         PARTITION p2019 VALUES LESS THAN (2019),
         PARTITION pmax VALUES LESS THAN MAXVALUE
      );
      

      在这里,我将分区值中的年份指定为 int 即 2018 / 2019,而不是像 '2018' / '2019' 中的字符串

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多