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';   -- 替换为您的表名
相关推荐
JY.yuyu2 小时前
Docker搭建Web安全渗透测试靶场
运维·docker·容器
En^_^Joy2 小时前
Docker入门:快速安装与实战指南
运维·docker·容器
70asunflower2 小时前
Docker 镜像的完整内容解析
运维·docker·容器
sg_knight2 小时前
如何通过 SQL*Plus 连接 Oracle 数据库(使用 Instant Client)
运维·数据库·sql·oracle·database·关系型数据库·sql puls
API开发2 小时前
apiSQL网关 for Docker 离线安装和升级教程
运维·docker·容器·api·api网关·apisql·替代graphql
木子欢儿2 小时前
探索 OpenMediaVault 安装
linux·运维·服务器
Linux运维技术栈2 小时前
运维安全: SSH 公钥认证算法加固
linux·运维·安全
斯普信专业组2 小时前
Nacos-MCP 融合架构:运维nacos的MCP服务项目
运维·nacos·架构
小钻风33662 小时前
Docker入门基础知识(一)
运维·docker·容器