在mysql5.6官方文档中关于full table scan的介绍如下:
An operation that requires reading the entire contents of a table, rather than just selected portions using an index. Typically performed either with small lookup tables, or in data warehousing situations with large tables where all available data is aggregated and analyzed. How frequently these operations occur, and the sizes of the tables relative to available memory, have implications for the algorithms used in query optimization and managing the buffer pool.
The purpose of indexes is to allow lookups for specific values or ranges of values within a large table, thus avoiding full table scans when practical.
大意:
Full table scan是一种需要读取表全部数据的操作,常见于读取小表的全部内容,或者在数仓中查询大表所有数据用以分析或聚合。
索引的目的是允许在一个大表中查找特定的值或值的范围,从而在实际操作时避免全表扫描。
一、发生全表扫描的条件
在表数据非常大时,全表扫描往往是灾难性的。当explain输出的type列的值为ALL时,表示这一步发生了全表扫描操作。一般出现以下条件时会发生全表扫描:
1、表数据量很小,走索引查询比全表扫描更麻烦;这对于少于10行且行长度较短的表来说很常见;
2、SQL的on子句或者where子句涉及到的列上没有索引;
3、将索引列与常量值进行比较,并且MySQL已经计算(基于索引树)常量覆盖了表中太大的一部分,而表扫描会更快。换言之,即便字段选择性高且有索引,但要取出的数据行太多,也不会走索引,这个比例一般是20%-30%;
4、对于低选择性的索引列,一个键值可能会匹配N多行数据,这个时候也不走索引而发生全表扫描。
二、优化全表扫描
对于小数据量的表,表扫描通常是合适的。对于大数据量的表,可以尝试以下技术来避免优化器发生全表扫描:
1、通过“ANALYZE TABLE tb_name”语句更新表上的索引统计信息;对于innodb表和myisam表来说,执行该语句时会加表级S锁;
2、使用 “FORCE INDEX”语句强制走索引,告诉优化器走该索引更合适;
3、修改max_seeks_for_key参数值,例如:SET max_seeks_for_key=1000。该参数的含义:根据键查找行时,限制假定的最大查找次数;通过调低该参数值,以使优化器更喜欢索引而不是表扫描。