TDSQL创建分区表

最近因TDSQL存放物联感知数据量增长较快,因此为提升性能,使用分区表。

建表

sql 复制代码
DROP TABLE `data_iot2`;
CREATE TABLE `data_iot2` (
  `id` bigint(20) NOT NULL COMMENT '分布式ID',
  `device_id` varchar(64) NOT NULL COMMENT '设备唯一标识',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '数据创建时间',
  `metric_name` varchar(128) NOT NULL,
  `metric_value` decimal(18,4) NOT NULL,
  `unit` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`, `device_id`, `create_time`),
  KEY `idx_data_iot2_device_id_create_time` (`device_id`, `create_time`),
  KEY `idx_data_iot2_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
PARTITION BY RANGE (TO_DAYS(`create_time`)) (
    PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
    PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')),
    PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')),
    PARTITION p_max VALUES LESS THAN MAXVALUE
);

为何如此设计?

1、满足分区规则:分区键是 TO_DAYS(create_time),所以 create_time必须在主键中。

2、保证全局唯一性:id本身是分布式ID,理论上全局唯一。但MySQL的分区逻辑无法感知这一点,它要求主键能唯一标识整个表的每一行。通过将 id设为主键的第一列,我们确保了主键的唯一性。

3、包含查询键:device_id是高频查询条件,将其加入主键,可以让某些查询(如 WHERE device_id = ? AND create_time = ?)直接通过主键定位,速度极快。

潜在缺点:

主键过长:InnoDB的主键是聚集索引,其叶子节点存储了整行数据。一个过长的主键会增加索引占用的空间,并可能降低基于主键的插入和更新性能。不过,对于您的字段类型,这个长度尚可接受。

注意点

重要警告:在分区表中,类似WHERE create_time > '2026-02-10 10:00:00'这种查询的性能是灾难性的!因为它会导致MySQL的查询优化器无法有效进行分区裁剪(Partition Pruning),可能会变成全分区扫描,即扫描 p202601, p202602, p202603, p_max所有分区,性能极低。强烈建议避免使用此类查询,或者在业务上保证此类查询必须带上 device_id或其他能缩小范围的条件。

插入测试数据

sql 复制代码
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (1, '1', '2026-01-01 17:27:55', '1', 1.0000, '1');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (2, '2', '2026-01-02 17:28:11', '2', 2.0000, '2');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (3, '3', '2026-02-02 17:28:29', '3', 3.0000, '3');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (4, '4', '2026-02-04 17:28:42', '4', 4.0000, '4');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (5, '5', '2026-03-19 17:28:52', '5', 5.0000, '5');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (6, '6', '2026-05-30 17:29:03', '6', 6.0000, '6');
INSERT INTO `test`.`data_iot2` (`id`, `device_id`, `create_time`, `metric_name`, `metric_value`, `unit`) VALUES (7, '7', '2026-06-09 18:02:44', '7', 7.0000, '7');

验证

1、执行以下查询计划

sql 复制代码
EXPLAIN SELECT * FROM `data_iot2` WHERE create_time > '2026-01-01' and create_time < '2026-02-01'

可以看到定位到了分区p202601上

2、执行以下查询计划

sql 复制代码
EXPLAIN SELECT * FROM `data_iot2` WHERE create_time = '2026-06-09 18:02:44'

由于没有p202606分区,因此定位了p_max分区,注意这里即使重新创建p202601分区,原有已经入库的数据也不会自动挪到新建的分区上

3、执行以下查询计划

sql 复制代码
EXPLAIN SELECT * FROM `data_iot2` WHERE create_time > '2026-06-09 18:02:44'

从查询计划看,可以看到查询了多个分区

其他

增加分区

sql 复制代码
ALTER TABLE `data_iot2`
REORGANIZE PARTITION p_max INTO (
    -- 1. 定义新的2026年4月分区
    PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
    -- 2. 重新定义p_max,作为新的"未来"分区
    PARTITION p_max VALUES LESS THAN MAXVALUE
);

查询表的所有分区

sql 复制代码
SELECT
    PARTITION_NAME,           -- 分区名 (如 p202310, p_max)
    PARTITION_ORDINAL_POSITION, -- 分区在表中的位置序号 (从1开始)
    TABLE_ROWS,               -- 分区中大约的行数 (注意:是估计值,非精确值!)
    PARTITION_DESCRIPTION,    -- 分区的定义描述 (如 VALUES LESS THAN (202311))
    NODEGROUP,                -- 节点组 (用于NDB集群,InnoDB表通常为空)
    TABLESPACE_NAME           -- 表空间名 (通常为空,除非使用了独立的表空间)
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'test' -- 替换为您的数据库名
    AND TABLE_NAME = 'data_iot2';   -- 替换为您的表名
相关推荐
日取其半万世不竭5 小时前
用 Portainer 可视化管理 Docker:容器再多也不用背命令了
运维·docker·容器
Sirens.7 小时前
MySQL表设计进阶-约束范式连接索引与事务
android·数据库·mysql
动恰客流统计8 小时前
ReID边缘计算视觉统计:餐饮店客流增长的数字化破局路径
java·大数据·运维·人工智能
Oo大司命oO10 小时前
藏在正则表达式里的陷阱
数据库·mysql·正则表达式
砍材农夫12 小时前
运维|devops|jenkins构建应用发布
运维·jenkins·devops
△曉風殘月〆12 小时前
如何在Linux中安装Qt开发环境
linux·运维·qt
三十岁老牛再出发14 小时前
07.26每日总结
linux·c语言·mysql
雨的旋律209915 小时前
ubuntu2604
linux·运维·服务器
xieliyu.15 小时前
MySQL 存储过程详解:概念、创建与删除全教程
开发语言·数据库·mysql
Eloudy15 小时前
ubuntu 22.04安装 cuda 12.8.2
linux·运维·ubuntu