两个表做join的时候,mysql 一般会对两个表进行交叉匹配, 匹配算法可以参考 MySQL 有几种Join
今天在调试mysql的性能时,遇到一个奇怪的问题, 如下图:
驱动表9万条数据, 被驱动表80万条数据,jion 列是都存在索引的,explain 分析的结果却是走Block Nested-Loop Join。
这有点颠覆认知啊!
注意到这个被驱动表的索引列Cardinality =1, 查证后数据确实存在问题,被驱动表的80万条数据基本重复。 暂且抛开数据正确性不论,这个查询为何不走 Index Nested-Loop Join 呢?
后面对被驱动表的数据进行修复之后,再执行分析,此时就走Index Nested-Loop Join了。
2222.png
初步分析,可能mysql的优化器在分析决定应该是用Index Nested-Loop Join 还是 Block Nested-Loop Join 时,会根据索引的聚集度(也就是Cardinality)来判断,比如Cardinality=1, 表示只有一条索引,其实也表示这个索引的利用率并不高, 可能在性能还不及走索引。
实际上, 我们可以推测:mysql优化器在判断Cardinality很小时, 可以判断出该表的记录数很少,那么直接把驱动表的数据全部加载到内存中逐个与被驱动表进行匹配,可能更快。 走索引需要的时间为: 9万多次索引查询+ 查询数据列, 如果走block的, 被驱动表的数据的查找索引的时间省去, 当然, 这种情况只有在被驱动表的数量很小的极端情况下才会成立。
当然, 这一切只是我的猜测而已。
网友评论