在过去两年里,我们致力于打造 PlanetScale Insights 成为最佳内置 MySQL 数据库监控工具。今天,我们带来了一个重要升级:模式推荐 功能。
通过模式推荐,你可以自动获得优化建议,以提升数据库性能、减少内存和存储使用,并根据生产数据库流量改进数据库模式。
模式推荐利用查询级别的遥测数据生成量身定制的 DDL(数据定义语言)语句建议,这些语句可以直接应用到数据库分支并最终部署到生产环境中。


如何使用模式推荐

要查看你的数据库的模式推荐,进入 PlanetScale 数据库的“Insights”选项卡并点击“查看推荐”。在这里,你可以看到当前开放的数据库推荐列表。
此外,如果你订阅了数据库的每周数据库报告,你还会收到一封包含初步推荐的邮件。
示例:添加索引的推荐
每条推荐会包含以下内容:

  • 推荐变更的解释,包括推荐变更带来的部分好处(如减少内存和存储使用、降低执行时间、防止 ID 耗尽等)
  • 推荐影响的模式或查询
  • 应用推荐所需的具体 DDL 语句
  • 可选项:将推荐的变更应用到一个分支以进行测试和安全迁移

你应该根据你的具体使用场景评估每条推荐。阅读模式推荐的文档可以了解每个推荐的更多信息。
在充分理解推荐内容后,你可以通过以下方式应用推荐:

  1. 通过几次点击直接在数据库分支中应用推荐内容;
  2. 在你的应用或 ORM(对象关系映射)代码中直接进行相应的模式变更。

可在文档中了解更多关于应用推荐的信息。


PlanetScale 如何检测数据库模式推荐

我们构建了一套系统,内部称之为“Schema Advisor”(模式顾问),它可以生成模式推荐,并在模式变更关闭现有开放推荐时进行感知。
每当生产分支的模式在 PlanetScale 中发生变更时,会向 Kafka 发送一个事件。这会触发后台任务对模式进行检查以发现潜在建议。
对于某些推荐(如查找重复索引),我们仅通过模式即可确定。而对于其他推荐(如索引推荐),我们还使用最近查询的性能数据与统计信息。
在索引推荐中,我们首先通过 Insights 的查询数据确定潜在的慢查询候选项,然后使用 Vitess 的查询解析器与语义分析工具提取查询中的潜在可索引列。
在添加索引时,列的顺序至关重要。为了获得正确的列顺序,我们对 MySQL 的分支进行了修改,新增了另一种 ANALYZE TABLE ... UPDATE HISTOGRAM 命令,它允许我们提取每列的基数(唯一值数量)而不影响数据库的统计表。
结合所有这些信息,我们便可以针对数据库模式提供优化建议。


当前支持的模式推荐

今天,我们发布了四种不同的模式推荐,未来会添加更多:

  1. 为低效查询添加索引
  2. 删除冗余索引
  3. 防止主键 ID 耗尽
  4. 删除未使用的表

为低效查询添加索引

索引是关系型数据库性能的关键。如果没有索引或索引不理想,MySQL 可能需要扫描大量行以满足仅匹配少数记录的查询。这会导致查询缓慢以及数据库性能下降。合适的索引可以将查询执行时间从数小时减少到毫秒。你可以在这篇文章中阅读更多关于数据库索引的内容。
Insights 每日扫描你的查询性能数据,识别过去 24 小时内发出的高频查询,并根据读取行数与返回行数的高汇总比率确定低效查询。随后,它会解析查询以提取可索引列,估算每列的基数(唯一值数量)以确定最佳列顺序,并建议合适的索引。

删除冗余索引

虽然索引能显著提高查询性能,但不必要的索引会降低写入速度,并消耗额外的存储和内存。
每当模式发生变化时,Insights 会扫描你的模式以查找冗余索引,并建议删除以下两类索引:

  • 完全重复的索引:索引的列及其顺序完全相同;
  • 左前缀重复的索引:索引的列及其顺序为另一索引的前缀;

冗余索引非常常见。我们最初的一组推荐发现,33% 的 PlanetScale 数据库存在冗余索引,可以通过删除它们获益。

防止主键 ID 耗尽

随着新行的插入,自增主键可能会超过底层列类型的最大允许值。当列达到最大值时,向表插入数据将失败,可能导致你的应用中断。历史上有许多高调的停机事件源于此问题,而通过监控可以很好地防范。
Insights 每日扫描数据库模式中的所有 AUTO INCREMENT 主键,并检查当前的 AUTO INCREMENT 值以识别可能接近主键 ID 耗尽的情况。如果某列的值超过最大允许值的 60%,它会建议将底层列改为更大的类型。此外,Insights 会扫描查询以解析连接与相关子查询以查找外键,并建议增大相关列的大小。

删除未使用的表

删除未使用的表可以帮助清理不再需要的数据并减少存储。如果表较大,还能缩短备份与恢复时间。
Insights 每日扫描你的查询性能数据,识别哪些表已经超过四周未被查询且年龄超过四周。


示例:添加一个新索引

让我们通过一个示例来演示如何将一条新增索引推荐应用到数据库。首先,我们创建一个简单的 posts 表:

CREATE TABLE `posts` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255),
  `text` text,
  PRIMARY KEY (`id`)
)

在表进入生产环境后,两个不同的查询开始对其进行操作:

  1. 插入行到 posts 表的一个循环查询;
  2. 按循环查询 posts.title 的语句:
SELECT posts.id FROM posts WHERE posts.title = ?

当我们向 posts 表插入更多行时,与 posts.title 相关的查询的 p50 时间线性增加。此时,我们的查询接近一秒,表现非常糟糕。
幸运的是,“新增索引”的推荐每天运行一次,可以识别出这一查询模式将因索引获益。在推荐中,我们看到可利用新索引的查询列表,以及会创建新索引的 DDL 描述: 推荐内容:在 posts 表上添加名为 idx_posts_on_title 的索引**
我们可以使用“创建并应用”选项,在 PlanetScale 中创建一个数据库分支并应用推荐的 DDL。然后,在分支上使用现有查询测试所有内容后,部署到生产环境中。
正如预期,在推荐部署到生产后,由于新增索引,p50 查询时间显著降低。



引入模式推荐功能插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.choupangxia.com/2025/09/14/introducing-schema-recommendations/