PolarDB-X SQL(MySQL 兼容性聚焦)
为 PolarDB-X 2.0 企业版(分布式版)AUTO 模式数据库编写、审查和适配 SQL,避免“在 MySQL 上能跑,在 PolarDB-X 上失败”的问题。
架构:PolarDB-X 2.0 企业版(CN 计算节点 + DN 存储节点 + GMS 元数据服务 + CDC 日志节点) + AUTO 模式数据库
适用范围:
- PolarDB-X 2.0 企业版(又称分布式版) + AUTO 模式数据库
不适用于:
- PolarDB-X 1.0(DRDS 1.0)
- PolarDB-X 2.0 标准版
- PolarDB-X 2.0 企业版 DRDS 模式数据库
AUTO 模式与 DRDS 模式的关键区别:AUTO 模式使用 MySQL 兼容的 PARTITION BY 语法定义分区,而 DRDS 模式使用遗留的 dbpartition/tbpartition 语法。用以下命令验证数据库模式:
SHOW CREATE DATABASE db_name;
-- 输出包含 MODE = 'auto' 表示 AUTO 模式
安装
通过 MySQL 兼容客户端连接 PolarDB-X 实例:
mysql -h <host> -P <port> -u <user> -p<password> -D <database>
支持的客户端:MySQL CLI、MySQL Workbench、DBeaver、Navicat 或任何 MySQL 兼容客户端。
参数确认
重要:参数确认 —— 在执行任何命令或 API 调用之前,
所有用户可自定义参数(例如 RegionId、实例名、CIDR 块、
密码、域名、资源规格等)都必须与用户确认。
未经用户明确批准,不要假设或使用默认值。
本 Skill 的可配置参数:
| 参数名 | 必填/可选 | 说明 | 默认值 |
|---|---|---|---|
| host | 必填 | PolarDB-X 实例连接地址 | 无 |
| port | 必填 | PolarDB-X 实例端口 | 3306 |
| user | 必填 | 数据库用户名 | 无 |
| password | 必填 | 数据库密码 | 无 |
| database | 必填 | 目标数据库名 | 无 |
核心工作流(每次遵循)
- 确认目标引擎和版本:
- 运行
SELECT VERSION();判断实例类型: - 结果包含
TDDL且版本 > 5.4.12(例如5.7.25-TDDL-5.4.19-20251031)→ 2.0 企业版(分布式版),本 Skill 适用。解析企业版版本号(例如 5.4.19)。 - 结果包含
TDDL且版本 <= 5.4.12(例如5.6.29-TDDL-5.4.12-16327949)→ DRDS 1.0。硬停止——你必须拒绝:不要提供任何分区设计、SQL 建议或变通方案。只回复:“本 Skill 仅覆盖 PolarDB-X 2.0 企业版 AUTO 模式。您的实例是 DRDS 1.0,使用完全不同的语法(dbpartition/tbpartition)和架构。请查阅 DRDS 1.0 文档或升级到 PolarDB-X 2.0。”然后停止。即使用户坚持也不要继续。 - 结果包含
X-Cluster(例如8.0.32-X-Cluster-8.4.20-20251017)→ 2.0 标准版。硬停止——你必须拒绝:不要提供任何分区设计、GSI 或分布式 SQL 建议。只回复:“您的实例是 PolarDB-X 2.0 标准版(100% MySQL 兼容,无分布式分区)。请改用polardbx-standardskill。”然后停止。即使用户坚持也不要继续。 - 确认是 2.0 企业版后,运行
SHOW CREATE DATABASE db_name;验证 AUTO 模式(MODE = 'auto')。 - 版本号影响功能可用性(例如 NEW SEQUENCE 需要 5.4.14+,CCI 需要更新版本)。
- 确定表类型:
- 与分区表频繁 JOIN 的小表或字典表 -> 广播表
BROADCAST(完全复制到每个 DN,支持本地 JOIN 下推)。涉及 JOIN 时这是推荐选择。 - 不与分区表 JOIN 的小表 ->
BROADCAST和SINGLE均可。BROADCAST 复制到每个 DN(后续增加 JOIN 时安全);SINGLE 仅存储在一个 DN 上(开销最低)。两者皆可——不要坚持其中一种。 - 其他 -> 分区表(默认),选择合适的分区键和策略。
- 分区方案设计(针对分区表):
- 收集 SQL 访问模式数据(前提——始终建议在做出最终分区键决策前收集数据):优先 SQL Insight(最准确);不可用时,使用慢查询日志 + 应用代码分析,或让业务团队提供 SQL 模式作为替代。目标是获得该表的 SQL 模板清单(查询字段、执行频率、返回行数)。
- 分区键选择——综合多维度分析:列出所有候选字段,然后在做出推荐前对每个候选字段评估所有以下维度。不要仅基于单一维度推荐:
- 等值查询比例:该字段作为等值条件出现的 SQL 模板比例。
- 基数:不同值的数量;越高表示数据在各分区分布越均匀。
- 热点风险:少数值是否占据大部分数据(例如订单表中,某些 buyer_id 可能占数百万行而其他很少)。
- 主键/唯一键状态:PK/UK 天然具有最高基数和零热点风险。
- 语义分析:从表类型和字段含义推断查询模式。例如订单表中的 order_id 肯定被频繁查询(订单详情查询、状态检查、支付回调),即使用户只提到 buyer_id 查询。
最佳分区键是在所有维度综合得分最高的候选。对非分区键字段的高频查询可通过创建 GSI 优化。经典示例:订单表 → order_id(PK,最高基数,零热点,语义上查询频率高)作为分区键 + buyer_id 上的 GSI(buyer 维度查询比例高,但存在潜在倾斜风险,因为某些买家产生的订单远多于其他)。
- GSI 选择:根据写入量决定策略——写入量低的表可自由创建 GSI;为高频非分区键查询字段创建 GSI;低基数字段和时间字段不适合 GSI;总是与其他字段组合出现且从不单独出现的字段不需要单独的 GSI。GSI 类型:返回行数少用常规 GSI,一对多用 Clustered GSI,唯一约束用 UGSI。GSI 语法必须包含
PARTITION BY KEY(...) PARTITIONS N—— 完整语法见 gsi.md。 - 分区算法:约 90% 工作负载使用单级 HASH/KEY;订单类多维查询使用 CO_HASH;基于时间的数据清理使用 HASH+RANGE;多租户使用 LIST+HASH。单列时,HASH 和 KEY 等价。
- 分区数量:256 适合绝大多数工作负载;应为 DN 节点数的数倍;保持单分区在 1 亿行以下。
- 迁移工作流(单表转分区表三步法):(1) 先转为 1 个分区的分区表(保留唯一性)-> (2) 创建所需 GSI/UGSI -> (3) 改为目标分区数。详情见 partition-design-best-practice.md。
- 生成 SQL 时使用 PolarDB-X 安全默认值:
- 避免不支持的 MySQL 特性(存储过程/触发器/EVENT/SPATIAL 等)。
- 使用
KEY或HASH分区,而非 MySQL 的 AUTO_INCREMENT 主键写入热点。 - 需要非分区键查询时,考虑创建全局二级索引(GSI)。
- 如果用户提供 MySQL SQL,执行兼容性检查:
- 替换不支持的特性并提供 PolarDB-X 替代方案。
- 清楚标记行为差异和版本要求。
- SQL 慢或报错时,使用 PolarDB-X 诊断工具:
EXPLAIN查看逻辑执行计划。EXPLAIN EXECUTE查看下推到 DN 的物理执行计划。EXPLAIN SHARDING查看分片扫描详情并检查全分片扫描。EXPLAIN ANALYZE实际执行并收集运行时统计。
关键差异速查
- 三种表类型:单表(
SINGLE)、广播表(BROADCAST)、分区表(默认);根据数据量和访问模式选择。 - 分区表:支持 KEY/HASH/RANGE/LIST/RANGE COLUMNS/LIST COLUMNS/CO_HASH + 二级分区(49 种组合)。
- 主键和唯一键:分为 Global(全局唯一)或 Local(分区内唯一);单表/广播表/自动分区表始终为 Global;手动分区表当分区列是 PK/UK 列的子集时为 Global,否则为 Local(存在数据重复和 DDL 失败风险)。关键原则:优先从现有 PK/UK 列中选择分区键,以自然保证全局唯一——不要修改用户现有主键定义来添加分区列。
- 全局二级索引 GSI:解决非分区键查询的全分片扫描问题,支持 GSI / UGSI / Clustered GSI 类型。关键:GSI 必须指定自己的 PARTITION BY 子句——它是独立分区的表,不是普通 MySQL 索引。正确语法:
-- ✅ 正确:带 PARTITION BY 子句的 GSI
GLOBAL INDEX g_i_seller(seller_id) PARTITION BY KEY(seller_id) PARTITIONS 16
CLUSTERED INDEX cg_i_buyer(buyer_id) PARTITION BY KEY(buyer_id) PARTITIONS 16
-- ❌ 错误:缺少 PARTITION BY(这不是 MySQL INDEX 语法)
GLOBAL INDEX gsi_seller(seller_id)
经典分区设计——订单表:候选是 order_id(PK)和 buyer_id。综合分析:order_id 基数最高(每行唯一)、零热点风险、PK 状态且语义上查询频率高(订单详情/状态/支付查询);buyer_id 有高 buyer 维度查询比例但存在潜在分布倾斜(某些买家产生的订单远多于其他)。结论:order_id 作为分区键 + buyer_id 上的 Clustered GSI。
- 聚簇列式索引 CCI:行列混合存储,通过
CLUSTERED COLUMNAR INDEX加速 OLAP 分析查询。 - Sequence:全局唯一序列,默认类型为
NEW SEQUENCE(5.4.14+),是 AUTO_INCREMENT 的分布式替代。 - 分布式事务:基于 TSO 全局时钟 + MVCC + 2PC,默认强一致;单分片事务自动优化为本地事务。
- 表组:相同分区规则的表绑定到同一表组,确保 JOIN 计算下推,避免跨分片数据洗牌。
- TTL 表:基于时间列自动过期和清理冷数据,可与 CCI 配合实现冷热数据分离。
- 不支持的 MySQL 特性:存储过程/触发器/EVENT/SPATIAL/GEOMETRY/LOAD XML/HANDLER 等。
- 不支持 STRAIGHT_JOIN / NATURAL JOIN:改用标准 JOIN 语法。
- 不支持 := 赋值运算符:将逻辑移到应用层。
- 不支持 HAVING/JOIN ON 子句子查询:将子查询重写为 JOIN 或 CTE。
最佳实践
- 选择合适的表类型:与分区表 JOIN 的小表/字典表使用广播表。不与分区表 JOIN 的小表,BROADCAST 和 SINGLE 均可。其他一切使用分区表。
- 通过综合多维度分析选择分区键:始终建议先收集 SQL 访问模式数据(优先 SQL Insight)。对每个候选字段,分析所有维度——等值查询比例、基数、热点风险、PK/UK 状态和字段语义——然后选择综合得分最高的候选。绝不基于单一维度做决定。记住从表/字段语义推断查询模式(例如订单表中的 order_id 肯定被频繁查询用于订单详情、状态检查、支付回调)。
- 优先从 PK/UK 列选择分区键:选择分区键时,优先从现有主键或唯一键列中选择——这自然使 PK/UK 为 Global(全局唯一),无需任何 schema 变更。不要修改用户现有主键定义来添加分区列。当 PK 列不适合作为分区键时(例如无业务含义的自增 id),选择其他业务列作为分区键也完全合理——此时 PK 变为 Local(仅分区内唯一);向用户解释 Local PK 风险并确保自增/Sequence 机制避免跨分区 PK 冲突。
- 明智创建 GSI:根据写入量决定 GSI 策略;返回行数少用常规 GSI,一对多用 Clustered GSI,唯一约束用 UGSI;不为低比例 SQL 创建 GSI;用
INSPECT INDEX定期清理冗余 GSI。每个 GSI 必须有自己的PARTITION BY KEY(...) PARTITIONS N子句;绝不写不带 PARTITION BY 的裸GLOBAL INDEX idx(col)。 - 使用 256 个分区:256 个分区适合绝大多数工作负载,应为 DN 节点数的数倍。
- 单表转分区表使用三步法:先转为 1 个分区(保留唯一性)-> 创建 GSI/UGSI -> 改为目标分区数,避免唯一性约束缺口。
- 不要为低比例 SQL 强制分区键命中:分区设计是务实的工作;低 QPS 跨分片查询总成本有限,不要为每个查询字段创建 GSI。
- 使用表组优化 JOIN:将频繁 JOIN 的表用相同分区规则绑定到同一表组。
- 避免不支持的 MySQL 语法:不要使用存储过程、触发器、EVENT、SPATIAL、NATURAL JOIN、
:=等。 - 避免 HAVING/JOIN ON 中的子查询:重写为 JOIN 或 CTE。
- 使用 EXPLAIN 命令诊断:对于 SQL 性能问题,优先使用
EXPLAIN SHARDING和EXPLAIN ANALYZE。 - Online DDL 前检查长事务:执行 DDL 前检查长事务,避免 MDL 锁等待。
- 使用 TTL 表管理冷数据:对于有时间属性的大表,使用 TTL 表自动清理过期数据。
- 使用 Keyset 分页实现高效分页:避免
LIMIT M, N深度分页(成本 O(M+N),分布式系统中更大);记录每批最后一行的排序值作为下一批的 WHERE 条件;排序列可能有重复时,使用(sort_column, id)元组比较;确保排序列上有合适的复合索引。 - Range 分区表使用自动添加分区:PolarDB-X 使用专有的
ALTER TABLE ... MODIFY TTL SET语法(带TTL_EXPR、TTL_PART_INTERVAL、ARCHIVE_TYPE、ARCHIVE_TABLE_PRE_ALLOCATE等多个参数)配置自动分区预创建。此语法不是标准 SQL,无法猜测——生成任何自动添加分区配置之前,你必须阅读 references/auto-add-range-parts.md 获取确切的 SQL 语法。 需要 5.4.20+ 版本。
参考链接
| 参考 | 说明 |
|---|---|
| references/create-table.md | CREATE TABLE 语法、表类型(单表/广播/分区)、分区策略、二级分区、分区管理 |
| references/partition-design-best-practice.md | 分区设计最佳实践:分区键/GSI/算法/数量选择、三步迁移、完整示例 |
| references/primary-key-unique-key.md | 主键和唯一键 Global/Local 分类、规则、风险和建议 |
| references/gsi.md | 全局二级索引 GSI/UGSI/Clustered GSI 创建、查询和限制 |
| references/cci.md | 聚簇列式索引 CCI 创建、使用和适用场景 |
| references/sequence.md | Sequence 类型(NEW/GROUP/SIMPLE/TIME)、创建和使用 |
| references/transactions.md | 分布式事务模型、隔离级别和注意事项 |
| references/mysql-compatibility-notes.md | MySQL 与 PolarDB-X 兼容性差异和开发限制 |
| references/explain.md | EXPLAIN 命令变体和执行计划诊断 |
| references/ttl-table.md | TTL 表定义、冷数据归档和清理调度 |
| references/online-ddl.md | Online DDL 评估、无锁执行策略、长事务检查、DMS 无锁变更 |
| references/pagination-best-practice.md | 高效分页:Keyset 分页、按分片遍历、索引要求、Java 示例 |
| references/auto-add-range-parts.md | Range 分区自动添加:基于 TTL 的分区预创建、一/二级配置、管理命令 |
| references/cli-installation-guide.md | 阿里云 CLI 安装指南 |
阿里云skills
◯ 评论 0