MySQL查询upper(name) = ‘A’name = upper(‘A’)哪个更快,我想在name列为索引的情况下,都知道后者更快。那么name列为非索引的情况哪个更快呢?

拥有多年代码经验的我,直觉就告诉我同样是后者更快,MySQL必定有优化,如果要说原因还确实触及到我的知识盲区了。

但是,MySQL可以告诉我原因。

1
2
3
4
EXPLAIN SELECT * FROM test.tt WHERE upper(`name`) = 'A';
SHOW WARNINGS;
EXPLAIN SELECT * FROM test.tt WHERE `name` = upper('A');
SHOW WARNINGS;

使用EXPLAIN后紧接着执行SHOW WARNINGS(也可使用OPTIMIZER_TRACE,详见Chapter 8 Tracing the Optimizer)。就可以看到MySQL优化后的SQL语句。

  • upper(name) = ‘A’
1
/* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`name` AS `name` from `test`.`tt` where (upper(`test`.`tt`.`name`) = 'A')
  • name = upper(‘A’)
1
/* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`name` AS `name` from `test`.`tt` where (`test`.`tt`.`name` = <cache>(upper('A')))

很明显,两者最大的区别就是<cache>标识了。

从MySQL的官方文档Extended EXPLAIN Output Format中可以看到如下说明。

  • (expr)

    The expression (such as a scalar subquery) is executed once and the resulting value is saved in memory for later use. For results consisting of multiple values, a temporary table may be created and <temporary table> is shown instead.

<cache>标识的表达式只计算一次,并且计算结果会保存到内存以供之后使用。