Mysql查询优化器的局限性

本篇文章主要是讲下查询优化器的局限性,这里mysql版本不同,也可能查询优化器的限制也不同,本文是基于5.6.41版本进行讲解和举例。

关联子查询的限制

Where条件中包含In的子查询,例如,select * from table1 where table1.id in (select id from table2 where table2.col1 = 1);
这个语句优化器并不是如我们所想的一样先执行子查询,获得table2.col1=1 的结果,之后再进行table1的查询。
而mysql会先关联table1表,因为需要table1的id字段。所以mysql认为无法先执行这个子查询。当然也不是所有的关联子查询性能都会很差,我们要根据实际情况进行测试,然后给出自己的判断。

union的限制

如果希望union的各个子句能够根据limit 只取部分结果集,或者希望能够先排序好在合并结果集的话,就需要在union的各个子句中分别使用这些子句。
例子:
(select first_name,last_name from sakila.actor order by last_name) union all (select first_name,last_name from sakila.customer order by last_name) limit 20
这个查询会把actor表中的记录和customer表中的记录都存放在一个临时表中,然后再从临时表中取出前20条记录。我们可以通过每个子查询中分别添加一个limit来减少临时表中的数据,但这里需要考虑取出来的数据顺序问题。

等值传递

当有一个非常大的IN()列表,而mysql优化器发现存在where、on或者using的子句,将这个列表的值和另一个表的某个列相关联。这时优化器会将in的列表复制到关联的各个表中,如果列表非常大,则会导致优化和执行都会变慢。

无法并行执行

mysql不支持多核并行执行查询

哈希关联

mysql不支持哈希关联(除去Memory存储引擎,这个引擎的索引都是哈希索引)

某些情况不支持松散索引扫描

假如我们有如下索引(a,b),有查询mysql>select …from tb1 where b between 2 and 3;
很显然我们的索引没有利用上,从而只能通过全表扫描找到匹配的行,如下图
图一:mysql通过全表扫描找到需要的记录
当然我应该还有更快的方法执行上面的查询。我们可以先扫描a列第一个值对应的b列的范围,然后在跳到a列第二个不同值扫描对应的b列的范围。如下图:
图二:使用松散索引扫描效率会更高,但是mysql现在还不支持这么做

从上图可以看出松散扫描已经跳过了所有不需要的记录。

最大值和最小值优化

对于min 和max查询,mysql的查询还是有瑕疵的,例如 select min(primary id) from tab1 wher tb1.name=”xx”
如果tb1.name没有索引的化,将会进行一次全表扫描。若mysql能进行主键扫描的化,我们读到的第一条记录就应该是我要找的最小值。当然我们也可以通过如下的方式进行控制:select (primary ID)from tb1 where tb1.name=”xx” limit 1;

java高级教程–安全

猜你喜欢

转载自blog.csdn.net/qq_18377515/article/details/81587453