-> Index lookup on t3 using TABLE_NAME (TABLE_NAME=t2.`TABLE_NAME`) (cost=0.25 rows=1) (actual time=0.059..0.059 rows=1 loops=1)
-> Index lookup on t1 using TABLE_SCHEMA (TABLE_SCHEMA=t2.TABLE_SCHEMA, TABLE_NAME=t2.`TABLE_NAME`) (cost=56.08 rows=129) (actual time=0.044..0.070 rows=3 loops=1)
1 row in set (0.00 sec)
mysql> explain analyze select count(1) from (select t1.TABLE_CATALOG, t2.TABLE_SCHEMA, t2.TABLE_NAME, t1.COLUMN_NAME, t1.DATA_TYPE, t3.CONSTRAINT_TYPE from test_col t1 inner join test_tab t2 on t1.TABLE_SCHEMA = t2.TABLE_SCHEMA and t1.table_name = t2.table_name inner join test_tc t3 on t2.TABLE_SCHEMA = t3.TABLE_SCHEMA and t2.TABLE_NAME = t3.TABLE_NAME ) t \G
-> Index lookup on t3 using TABLE_NAME (TABLE_NAME=t2.`TABLE_NAME`) (cost=0.25 rows=1) (actual time=0.007..0.008 rows=1 loops=10338)
-> Index lookup on t1 using TABLE_SCHEMA (TABLE_SCHEMA=t2.TABLE_SCHEMA, TABLE_NAME=t2.`TABLE_NAME`) (cost=1.79 rows=129) (actual time=0.010..0.172 rows=131 loops=10143)
1 row in set (2.13 sec)
mysql>
复制代码
从上面的分析结果来看,在驱动表t2执行Index scan on t2 using TABLE_SCHEMA这一步的时候,就存在很大的差异了,执行快的SQL在这一步只扫描了一行记录,耗时0.053毫秒,而执行快的SQL在这一步扫描数量基本上和执行计划估计的一致,扫描了10338行记录,耗时12.845毫秒;驱动表扫描记录越多,那么和后续表关联的nested loop join次数也越多,导致两条SQL执行时间差异巨大。
加大limit的返回限制为5000,驱动表t2扫描的行数增加至99行,执行时间增加至0.201毫秒
mysql> explain analyze select count(1) from (select t1.TABLE_CATALOG, t2.TABLE_SCHEMA, t2.TABLE_NAME, t1.COLUMN_NAME, t1.DATA_TYPE, t3.CONSTRAINT_TYPE from test_col t1 inner join test_tab t2 on t1.TABLE_SCHEMA = t2.TABLE_SCHEMA and t1.table_name = t2.table_name inner join test_tc t3 on t2.TABLE_SCHEMA = t3.TABLE_SCHEMA and t2.TABLE_NAME = t3.TABLE_NAME limit 5000) t \G*************************** 1. row ***************************
-> Index lookup on t3 using TABLE_NAME (TABLE_NAME=t2.`TABLE_NAME`) (cost=0.25 rows=1) (actual time=0.005..0.006 rows=0 loops=99)
-> Index lookup on t1 using TABLE_SCHEMA (TABLE_SCHEMA=t2.TABLE_SCHEMA, TABLE_NAME=t2.`TABLE_NAME`) (cost=56.08 rows=129) (actual time=0.011..1.171 rows=250 loops=20)