mysql> alter table t2 add index (i2);
mysql> explain select t1.i1, t2.i2 from t1, t2 where t1.i1 = t2.i2g
*************************** 1. row ***************************
id: 1
select_type: simple
table: t1
type: all
possible_keys: null
key: null
key_len: null
ref: null
rows: 1000
extra:
*************************** 2. row ***************************
id: 1
select_type: simple
table: t2
type: ref
possible_keys: i2
key: i2
key_len: 5
ref: sampdb.t1.i1
rows: 10
extra: using where; using index
我们可以看到性能提高了。t1的输出没有改变(表明还是需要进行全表扫描),但是优化器处理t2的方式就有所不同了:
? 类型从all改变为ref,意味着可以使用参考值(来自t1的值)来执行索引查找,定位t2中合格的数据行。
? 参考值在参考(ref)字段中给出了:sampdb.t1.i1。
? 行数值从1000降低到了10,显示出优化器相信对于t1中的每一行,它只需要检查t2中的10行(这是一个悲观的估计值。实际上,在t2中只有一行与t1中数据行匹配。我们在后面会看到如何帮助优化器改善这个估计值)。数据行组合的全部估计值使1000×10=10000。它比前面的没有索引的时候估计出来的一百万好多了。
对t1进行索引有价值吗?实际上,对于这个特定的联结操作,扫描一张表是必要的,因此没有必要对t1建立索引。如果你想看到效果,可以索引t1.i1并再次运行explain:
mysql> alter table t1 add index (i1);
mysql> explain select t1.i1, t2.i2 from t1, t2 where t1.i1 = t2.i2g
*************************** 1. row ***************************
id: 1
select_type: simple
table: t1
type: index
possible_keys: i1
key: i1
key_len: 5
ref: null
rows: 1000
extra: using index
*************************** 2. row ***************************
id: 1
select_type: simple
table: t2
type: ref
possible_keys: i2
key: i2
key_len: 5
ref: sampdb.t1.i1
rows: 10
extra: using where; using index
上面的输出与前面的explain的输出相似,但是添加索引对t1的输出有一些改变。类型从null改成了index,附加(extra)从空的改成了using index。这些改变表明,尽管对索引的值仍然需要执行全表扫描,但是优化器还是可以直接从索引文件中读取值,根据不需要使用数据文件。你可以从myisam表中看到这类结果,在这种情况下,优化器知道自己只询问索引文件就能够得到所有需要的信息。对于innodb 和bdb表也有这样的结果,在这种情况下优化器可以单独使用索引中的信息而不用搜索数据行。
