
如果你曾试图加快运行缓慢的查询想必有人会建议你“只需查看执行计划”。这是一条不错的建议但如果你之前从未读过执行计划其输出内容可能会让你觉得像是看不懂的外星语言。本文将解释什么是执行计划、如何理解它们以及现代工具如何能大大减轻这一过程中的困扰。什么是查询执行计划当你运行 SQL 查询时数据库不会突然行动随机扫描表。相反查询优化器——每个主要数据库引擎内置的一个组件——会评估数十甚至数百种可能的数据检索策略估算每种策略的成本并最终确定它评估出最快的方案。执行计划是数据库中对该决策的书面记录。这与导航系统规划路线的方式颇为相似。如果你要求从 A 点前往 B 点导航系统会计算出最佳的行车路线它给你呈现的逐段指引就是该路线规划。理解这个规划能让你知道是行驶在高速公路上还是土路上更重要的是还能让你知道哪里是交通瓶颈所在。如何生成执行计划在大多数数据库中你可以通过在查询前加上“EXPLAIN关键字来生成计划。MySQL、PostgreSQL、MariaDB 和 SQLite 都支持这种语法而 SQL Server 则通过设置“SET SHOWPLAN_ALL ON”或在其工具中使用图形执行计划按钮来实现。不同数据库的输出会有所不同但其基本概念在所有数据库中是相同的。例如执行“EXPLAIN SELECT * FROM orders WHERE customer_id 42”这一操作并不会实际执行该查询。相反它会返回关于数据库计划“如何”执行该查询的描述。然后你可以根据这一描述来决定是否需要进行任何优化。需要注意的关键事项执行计划乍一看可能会让人感到有些难以理解因为它们会一次性呈现大量信息。不过幸运的是大多数性能问题通常会通过一些明显的迹象表现出来首先要留意的是全表扫描这种操作在 MySQL 中通常被标记为“ALL”在 PostgreSQL 中则被称为“Seq Scan”。这意味着数据库会读取表中的每一行以找到所需的数据——这相当于逐本书地在图书馆中查找而不是利用目录进行查找。对于小型表来说这种操作并无大碍但对于大型表而言几乎总是会造成问题。接下来请注意估计的行数。优化器的估计值会决定其决策过程因此如果估计值与实际情况相差甚远那么它所选择的方案可能会效率低下。较大的差异通常表明统计信息已过时对此你可以通过运行ANALYZE或UPDATE STATISTICS命令具体取决于你的数据库来修正。最后我们来看一下连接类型。嵌套循环连接在连接的一侧数据量较小的情况下表现良好而哈希连接则更适合处理较大的数据集。如果计划是在两个大型表之间选择使用嵌套循环连接那么添加适当的索引或重新设计查询可能会促使优化器采用更高效的策略。Navicat 可视化解释功能直接将原始的EXPLAIN输出以纯文本形式进行阅读需要一定的练习和耐心。而 Navicat 17 则通过显著增强的“可视化解释”功能解决了这一问题它能将执行计划数据转化为图形形式使得一目了然地理解变得非常容易。它不会逐行解析文本而是将执行计划以可视化流程的形式呈现出来每个操作都被显示为一个节点。Navicat 会突出显示成本高或效率低的操作这样你的目光就能立即被吸引到计划中需要关注的部分——无需进行任何心算对于那些更喜欢处理原始数据的用户Navicat 还提供了多种格式来展示同一计划包括可视化、JSON、文本和统计视图你可以根据需要切换查看这些不同的视图。这种多格式方法在跨不同数据库平台工作时尤其有用因为每个引擎的EXPLAIN输出格式不同。Navicat 会规范使用体验无论你使用的是 MySQL、PostgreSQL 或其他支持的数据库检查执行计划的工作流程都能保持一致。实用的规划分析方法通过执行计划来建立信心的最佳方法是先从你已经熟悉的一个查询开始生成其计划然后逐步跟踪该计划。添加一个索引并再次运行“EXPLAIN”命令。你会实时看到计划的变化这能帮助你直观地了解优化器如何应对模式变化。随着时间的推移识别出全表扫描或不准确的行估计这类情况会变得轻车熟路。执行计划不再让人感觉像是对内部细节的晦涩表述而开始让人觉得它确实就是它本身的样子即对数据库正在做什么以及为何如此操作的清晰解释。结语执行计划是开发人员或数据库管理员性能工具包中最强大的工具之一——而且它们的使用方法远比其表面看起来要容易得多。一旦你了解了全表扫描的样子、行计数估计的意义以及连接类型的不同之处你就具备了诊断大多数查询性能问题所需的大部分知识。将这些知识与像 Navicat内置的解释可视化工具这样的可视化工具相结合你就能在比预期更短的时间内从困惑中走向自信的诊断。