查询优化器的任务是找到执行 SQL 查询的最佳计划。因为“好”和“坏”之间的性能差异计划可能是数量级的(即秒与小时甚至天相比),大多数查询优化器(包括 MySQL 的优化器)都或多或少地在所有可能的查询评估计划中执行最佳计划的详尽搜索。对于连接查询,MySQL 优化器研究的可能计划的数量随着查询中引用的表的数量呈指数增长。对于少量表(通常少于 7 到 10 个),这不是问题。但是,当提交较大的查询时,查询优化所花费的时间很容易成为服务器性能的主要瓶颈。
一种更灵活的查询优化方法使用户能够控制优化器在搜索最佳查询评估计划时的详尽程度。一般的想法是,优化器调查的计划越少,编译查询所花费的时间就越少。另一方面,由于优化器跳过了一些计划,它可能会错过寻找最优计划的机会。
可以使用两个系统变量控制优化器对其评估的计划数量的行为:
该
optimizer_prune_level
变量告诉优化器根据对每个表访问的行数的估计跳过某些计划。我们的经验表明,这种“有根据的猜测”很少会错过最佳计划,并且可能会大大减少查询编译时间。这就是此选项optimizer_prune_level=1
默认启用 ( ) 的原因。但是,如果您认为优化器错过了更好的查询计划,则可以关闭此选项(optimizer_prune_level=0
) 的风险是查询编译可能需要更长的时间。请注意,即使使用这种启发式方法,优化器仍会探索大致呈指数级数量的计划。该变量告诉优化器应该查看每个不完整计划的“未来”
optimizer_search_depth
多远,以评估它是否应该进一步扩展。较小的值 可能会导致查询编译时间减少几个数量级。例如,如果接近查询中表的数量,具有 12、13 或更多表的查询可能很容易需要数小时甚至数天才能编译 。同时,如果用optimizer_search_depth
optimizer_search_depth
optimizer_search_depth
等于 3 或 4,优化器可能会在不到一分钟的时间内为同一个查询编译。如果您不确定 的合理值是多少optimizer_search_depth
,可以将此变量设置为 0 以告诉优化器自动确定该值。