MySQL-索引的使用
MySQL-索引的使用
关于索引的使用 比方说一个表给3个字段a, b, c 建立联合索引
使用索引的几种情况
-
全值匹配, 即查询条件中使用到a, b, c三个条件此时使用全值匹配三个字段都会用到具体是先查找a字段匹配的缩小查询范围,再在所有等于a字段的范围去查找等于b字段的, 随后再在等于a和b字段的范围内查找等于c字段的
-
匹配最左边的字段, 比方说我们的查询条件是where a = xx and b = xx 那么会去先查找等于a的数据说缩小查询范围再查找等于b的数据如果我们的条件是where a = xx and c = xx 那么只会使用到a字段, 如果我们的查询条件是where b = xx and c = xx 那么将不会使用到索引, 即我们的查询条件中必须包含最左边的列才会使用到我们的索引,
原因: 因为在我们的B+树页中联合索引是按照a, b, c索引的顺序进行排列的a字段相同则按照b字段顺序排, b字段顺序相同则通过c字段排。查找时通过二分法去页目录中查找数据对应的分组再往下查找, 如果没有按照索引建立的顺序则不会通过这个查找规则去查找
-
匹配列前缀, 如果我们的查询条件是where a like ‘xxx%’ 那么会通过字符集的比较规则去查找出xxx前缀开头的这些数据, 如果是where a like '%xx%'是不会使用索引的
-
匹配范围值, 必须使用到最左边的列, 我们的查询条件是 where a > ‘xx’ and a < ‘yy’ and b > ‘xx’ and b < 'yy’此时只会用到联合索引的a字段而b字段只能在a条件筛选完的范围内进行查找
-
精确匹配某一列并范围匹配另一列, where a = ‘xx’ a and b > ‘xx’ and b < ‘yy’ and c > ‘xx’ and c < ‘yy’ 此时会匹配到等于a列的值的数据, 再通过范围查找到b > ‘xx’ and b < ‘yy’ 但是没法使用到c列与第5点同理
-
用于排序 例如where a = ‘xx’ order by b, c 这样是可以使用到索引的
几种使用不到索引的情况
- ASC DESC 混用
- where子句中出现非排序使用到的索引列
- 排序列包含非同一个索引的列
- 排序列使用了复杂的表达式
-
用于分组 例如我们的select a,b,c count(*) from table group by a, b, c这个查询语句进行了三次分组先根据a一致的数据进行了一次分组, 再在a一致的数据中将b一致的分为更小的一组, 再在上一轮中a,b一致的中进行分组统计此时正好用到a,b,c三个字段组成的联合索引,由于我们的索引是按照a,b,c三个字段 排序的此分组是可以直接使用到B+树索引的
回表
什么是回表?
当我们使用二级索引(非聚簇索引)查询时, 会先在这个索引的B+树上找到对应的主键id再通过查找出的id去聚簇索引上通过id去找到对应查询的数据
这个过程会在两颗B+树上进行查找
如果我们的查询条件是select * from table where a = xx and b = xx c = xx 数据库字段有id, a, b, c, d, e 其中a, b, c字段是联合二级索引但是id, c, d, e字段没有在联合索引上, 此时需要查联合索引以外的数据则需要回表到聚簇索引上查找
注意: 需要回表的记录越多, 使用二级索引的性能就越低 ,甚至在某些时候宁愿全表扫描也不愿使用二级索引
什么时候使用二级索引什么时候全表扫描?
查询优化器会事先对表中的记录计算统计一些数据, 利用这个统计数据可以知道回表的数据的多少, 需要回表的数据越多则就越倾向全表扫描, 反之则倾向使用二级索引
覆盖索引: 为了避免回表带来的困扰 建议: **最好在查询的列中只包含索引列 **
如何挑选索引
-
只为搜索, 排序或分组的列创建索引
-
考虑列的基数
列的基数是指某一列中不重复的个数, 在记录行数一定的情况下,列的基数越大, 该列中的值越分散, 列的基数越小,该列中值越集中最好为列基数大的列建立索引
-
索引列的类型尽量小
-
索引字符串的前缀create index idx_name_birthday_phone_number (name(10), birthday, phone_number) tablename只用到了前10个字符这样是鼓励的,尤其是在字符串类型能存储的字符比较多的时候。
-
让索引列在比较列表中单独出现
例如我的SQL语句是select a from table where a>1这样是可以使用索引的但是select a from table where a * 2 > 1这样是无法使用索引的
-
主键插入顺序, 如果主键是忽大忽小的话, 数据进入到我们的B+树中是需要先查找到插入位置的, 而B+树主键索引是按照顺序进行排列的, 从中间位置的页插入是会导致页分裂和记录移位的, 会带来性能损耗, 所以建议主键是递增的