在mysql查询中,如果表没有索引的话,当查询执行时,需要从第一行数据到最后一行数据进行全表扫描。索引的目的就是辅助查询能快速定位到目标数据,然后获取查询结果。那么表是否有了索引就一定能加以应用,而不会进行全表扫面了呢?现实肯定不是这样的!!!
1全表扫描的场景
使用EXPLAIN分析SQL时,当列出执行计划表中type字段值为ALL时,代表需要全表扫描,全表扫描常会发生在以下场景中。
1所扫描的数据表非常小,因此全表扫描的速度要远快于使用索引,在小于10行或行数据比较短的表中更常见。
2在ON或WHERE子句中没有可以使用的索引列。
3在使用索引列与常量值比较,并且MySQL服务已经通过索引树计算出常量值覆盖了大部分表数据,此时使用全表扫描是比较快的。
4当前正在使用一个对于其他列来说基数较低的索引(每个索引值在另一列都有多行行对应),在这种情况下,使用索引可能会引起较多的索引查询,MySQL认为全表扫描比较快。
2避免全表扫描
对于小表而言,全表扫描因为对性能影响可以忽略所以该方式是最合适的,但是对于大表而言,使用以下操作可以帮助优化器对于是否进行全表扫描做出正确的判断:
1使用ANALYZETABLEtbl_name语句来更新被扫描表中索引的分布。
2对被扫描表使用FORCEINDEX语句来强制优化器对该表放弃全表扫描而使用索引,如下:
3设置启动参数--max-seeks-for-key=或使用参数SETmax_seeks_for_key=来通知优化器如果没有索引扫描会导致过千的索引查找。
3总结
对于性能开销忽略不计的小表全表扫描我们可以不予重视,但是对于其他情况多是索引设计不合理或应用不合理造成的。
许多数据库使用人员在遇到SQL执行性能不行时,就会狂加一片索引,殊不知,索引带来的便利性不是依赖于索引个数的,其本质是索引是否正确高效的在应用中发挥作用。对于现实应用中我们添加索引时常常需要考虑多个场景:
1该列是否在应用为唯一索引,如果不为唯一索引,重复值的出现概率为多少,如果重复值出现多,是否可以与其他列一起组合成为联合索引而降低其重复率;
2多个单独应用可能建立了多个索引,对于较大表而言,索引的大小与索引的维护也会对数据库性能产生重大影响,此时应该考虑是否能够将应用合并或根据应用特点将索引合并;
3表的操作中在insert、update和delete等涉及数据变化的操作中,也会设计到索引的维护。对于表内无效数据定时移除并备份,无效或低效索引的删除也会提高相关SQL语句的性能。