MariaDB 10.1.1: engine_condition_pushdown 标志已弃用

让我先讲个小故事。你坐在客厅壁炉旁,需要从图书馆拿一本书……呃,不对,抱歉,时代错了。你正在建造一个机械臂,它可以帮你开啤酒、冲咖啡或提供你选择的任何其他饮料……同时你还在建造下一个机械臂。所以,你——一手拿着烙铁,一手拿着 Arduino——让你的小弟弟从地下室拿一盒特定的电阻器(你意外地用完了)。问题在于——你弟弟还小,分不清电阻器和呼吸器。你解释说它是一个伸出两根电线的小东西。于是他开始来回跑,一箱箱地给你拿来各种伸出两根电线的小东西。

这大约就是我们在 MySQL 刚添加 NDB Cluster 时的状况。用户想要查找一行,比如 WHERE number_of_wires=2 AND size='small' AND type='resistor' and ohm=10000。优化器会设计一个执行计划,对 number_of_wires 列使用“ref”访问。然后 NDB Cluster 引擎开始从所有节点检索所有 number_or_wires=2 的行,并通过网络将所有这些行发送到服务器,结果却一次又一次地被拒绝,因为它们不满足 WHERE 条件的其余部分。

因此,你看,最初引擎条件下推是为 NDB Cluster 实现的。通过引擎条件下推,服务器可以将完整的 WHERE 子句发送给 NDB,NDB 会将其发送给所有节点,这样只有实际满足完整 WHERE 子句的行才会通过网络发送回服务器。如果 WHERE 子句对节点来说过于复杂(例如,它包含存储函数),NDB 只能推送一部分,让服务器强制执行其余部分。

但这并非完全完美。如果使用了引擎条件下推,服务器需要准备要推送的条件。在联接中,这意味着提取 WHERE 子句中不依赖于尚未读取的表中的数据的部分。这会给每个查询带来相当大的开销,即使它不使用 NDB Cluster。而大多数查询都不使用。因此,引擎条件下推默认是禁用的。

快进到 MariaDB。MariaDB 没有 NDB Cluster,但它有许多其他存储引擎。对于其中一些引擎,例如 SphinxSE,引擎条件下推不仅仅是一个有用的优化,而是一个要求,如果禁用了引擎条件下推,SphinxSE 根本无法正常工作。我们在 MariaDB 5.2 中通过实现一个覆盖解决了这个问题——引擎可以为其表启用引擎条件下推,即使对所有其他表禁用了该功能。对于不使用 SphinxSE 的查询没有开销。后来其他引擎也开始使用这个覆盖。

这就是我们最终陷入的奇怪境地,引擎条件下推默认全局禁用,但实际上所有可以使用引擎条件下推的引擎都通过这个覆盖使用了它。如果用户启用了引擎条件下推,它不会增加额外的优化或功能,只会增加服务器为无法使用推下条件的引擎准备条件的开销。

这就是为什么在 MariaDB 10.1.1 中,我们弃用了 engine_condition_pushdown 标志。你仍然可以写

SET optimizer_switch="engine_condition_pushdown=on";

但这除了打印弃用警告外,不会做任何事情。从 MariaDB 10.1.1 开始,对于支持它的引擎,引擎条件下推始终启用;对于不支持它的引擎,则始终禁用。