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必填目标数据库名

核心工作流(每次遵循)

  1. 确认目标引擎和版本:
  • 运行 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-standard skill。”然后停止。即使用户坚持也不要继续。
  • 确认是 2.0 企业版后,运行 SHOW CREATE DATABASE db_name; 验证 AUTO 模式(MODE = 'auto')。
  • 版本号影响功能可用性(例如 NEW SEQUENCE 需要 5.4.14+,CCI 需要更新版本)。
  1. 确定表类型:
  • 与分区表频繁 JOIN 的小表或字典表 -> 广播表 BROADCAST(完全复制到每个 DN,支持本地 JOIN 下推)。涉及 JOIN 时这是推荐选择。
  • 不与分区表 JOIN 的小表 -> BROADCASTSINGLE 均可。BROADCAST 复制到每个 DN(后续增加 JOIN 时安全);SINGLE 仅存储在一个 DN 上(开销最低)。两者皆可——不要坚持其中一种。
  • 其他 -> 分区表(默认),选择合适的分区键和策略。
  1. 分区方案设计(针对分区表):
  • 收集 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
  1. 生成 SQL 时使用 PolarDB-X 安全默认值:
  • 避免不支持的 MySQL 特性(存储过程/触发器/EVENT/SPATIAL 等)。
  • 使用 KEYHASH 分区,而非 MySQL 的 AUTO_INCREMENT 主键写入热点。
  • 需要非分区键查询时,考虑创建全局二级索引(GSI)。
  1. 如果用户提供 MySQL SQL,执行兼容性检查:
  • 替换不支持的特性并提供 PolarDB-X 替代方案。
  • 清楚标记行为差异和版本要求。
  1. 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。

最佳实践

  1. 选择合适的表类型:与分区表 JOIN 的小表/字典表使用广播表。不与分区表 JOIN 的小表,BROADCAST 和 SINGLE 均可。其他一切使用分区表。
  2. 通过综合多维度分析选择分区键:始终建议先收集 SQL 访问模式数据(优先 SQL Insight)。对每个候选字段,分析所有维度——等值查询比例、基数、热点风险、PK/UK 状态和字段语义——然后选择综合得分最高的候选。绝不基于单一维度做决定。记住从表/字段语义推断查询模式(例如订单表中的 order_id 肯定被频繁查询用于订单详情、状态检查、支付回调)。
  3. 优先从 PK/UK 列选择分区键:选择分区键时,优先从现有主键或唯一键列中选择——这自然使 PK/UK 为 Global(全局唯一),无需任何 schema 变更。不要修改用户现有主键定义来添加分区列。当 PK 列不适合作为分区键时(例如无业务含义的自增 id),选择其他业务列作为分区键也完全合理——此时 PK 变为 Local(仅分区内唯一);向用户解释 Local PK 风险并确保自增/Sequence 机制避免跨分区 PK 冲突。
  4. 明智创建 GSI:根据写入量决定 GSI 策略;返回行数少用常规 GSI,一对多用 Clustered GSI,唯一约束用 UGSI;不为低比例 SQL 创建 GSI;用 INSPECT INDEX 定期清理冗余 GSI。每个 GSI 必须有自己的 PARTITION BY KEY(...) PARTITIONS N 子句;绝不写不带 PARTITION BY 的裸 GLOBAL INDEX idx(col)
  5. 使用 256 个分区:256 个分区适合绝大多数工作负载,应为 DN 节点数的数倍。
  6. 单表转分区表使用三步法:先转为 1 个分区(保留唯一性)-> 创建 GSI/UGSI -> 改为目标分区数,避免唯一性约束缺口。
  7. 不要为低比例 SQL 强制分区键命中:分区设计是务实的工作;低 QPS 跨分片查询总成本有限,不要为每个查询字段创建 GSI。
  8. 使用表组优化 JOIN:将频繁 JOIN 的表用相同分区规则绑定到同一表组。
  9. 避免不支持的 MySQL 语法:不要使用存储过程、触发器、EVENT、SPATIAL、NATURAL JOIN、:= 等。
  10. 避免 HAVING/JOIN ON 中的子查询:重写为 JOIN 或 CTE。
  11. 使用 EXPLAIN 命令诊断:对于 SQL 性能问题,优先使用 EXPLAIN SHARDINGEXPLAIN ANALYZE
  12. Online DDL 前检查长事务:执行 DDL 前检查长事务,避免 MDL 锁等待。
  13. 使用 TTL 表管理冷数据:对于有时间属性的大表,使用 TTL 表自动清理过期数据。
  14. 使用 Keyset 分页实现高效分页:避免 LIMIT M, N 深度分页(成本 O(M+N),分布式系统中更大);记录每批最后一行的排序值作为下一批的 WHERE 条件;排序列可能有重复时,使用 (sort_column, id) 元组比较;确保排序列上有合适的复合索引。
  15. Range 分区表使用自动添加分区:PolarDB-X 使用专有的 ALTER TABLE ... MODIFY TTL SET 语法(带 TTL_EXPRTTL_PART_INTERVALARCHIVE_TYPEARCHIVE_TABLE_PRE_ALLOCATE 等多个参数)配置自动分区预创建。此语法不是标准 SQL,无法猜测——生成任何自动添加分区配置之前,你必须阅读 references/auto-add-range-parts.md 获取确切的 SQL 语法。 需要 5.4.20+ 版本。

参考链接

参考说明
references/create-table.mdCREATE 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.mdSequence 类型(NEW/GROUP/SIMPLE/TIME)、创建和使用
references/transactions.md分布式事务模型、隔离级别和注意事项
references/mysql-compatibility-notes.mdMySQL 与 PolarDB-X 兼容性差异和开发限制
references/explain.mdEXPLAIN 命令变体和执行计划诊断
references/ttl-table.mdTTL 表定义、冷数据归档和清理调度
references/online-ddl.mdOnline DDL 评估、无锁执行策略、长事务检查、DMS 无锁变更
references/pagination-best-practice.md高效分页:Keyset 分页、按分片遍历、索引要求、Java 示例
references/auto-add-range-parts.mdRange 分区自动添加:基于 TTL 的分区预创建、一/二级配置、管理命令
references/cli-installation-guide.md阿里云 CLI 安装指南

文档 3 / 6:alibabacloud-polardbx-ai-assistant