索引最好是让你的各个where、orderby和group by后面跟的字段都是联合索引的
最左侧开始
的部分字段,这样他们都能用上索引(索引顺序一致
)不要为字段基础小的字段建立索引,如只有1、0值
建立索引,
尽量使用那些基数比较大的字段
,就是值比较多的字段,那么才能发挥出B+树快速二分查找的优势来。尽量是对那些字段的类型比较小的列来设计索引
,比如说什么tinyint之类的,因为他的字段类型比较小,说明这个字段自己本身的值占用磁盘空间小,此时你在搜索的时候性能也会比较好一点。建立出来的索引其实类似于KEY my_index(name(20),age,course);假设name是varchar(255)类型的,但是在索引树里你对name的值仅仅提取前20个字符而已。
- where条件里搜索的时候就可以使用前20个字符在索引中搜索
- 但order by name、group by就不行
因为你插入的数据值可能根本不是按照顺序来的,很可能会导致索引树里的某个页就会自动分裂,这个页分裂的过程就很耗费时间,因此一般让大家设计索引别太多,建议两三个联合索引就应该覆盖掉你这个表的全部查询了。
建议
主键一定是自增
的,别用UUID之类的,因为主键自增,那么起码你的聚簇索引不会频繁的分裂
,主键值都是有序的,就会自然的新增一个页而已,但是如果你用的是UUID,那么也会导致聚簇索引频繁的页分裂。实际场景中,往往
where和order by是没法都用到索引
的设计索引的时候,必须把经常用做
范围查询
的字段放在联合索引的最后一个
,才能保证你SQL里每个字段都能基于索引去查询。在查询的时候如果有些字段是不使用的,可以用
in (所有枚举值)的方式
去写,这样可以让所有查询条件都用上你的索引,同时对范围查询的age字段必须放在最后一个,这样保证范围查询也能用上索引计算或者是函数
不能使用索引可以将一个范围查询,去增加一个字段,让这个字段变成枚举查询;
- where xx xxx and age>=xx and age<=xxx and
latest_login_time
>=xx(==原来==)- (province, city, sex, hobby, character, age,
latest_login_time
)
- (province, city, sex, hobby, character, age,
- 加一个
does_login_in_latest_7_days
,用户是否7天内登录的 字段- 索引改成(province, city, sex, hobby, character,
does_login_in_latest_7_days
, age) - 这个字段就是1,否则超过7天没登录,这个字段就是0
- where xx xxx and age>=xx and
does_login_in_latest_7_days=1
and age<=xxx(==现在==)
- 索引改成(province, city, sex, hobby, character,
- where xx xxx and age>=xx and age<=xxx and
针对一些
低基数字段筛选(比如性别筛选)+评分排序(比如对分数排序)
的查询场景,可以设计类似(sex, score)的辅助索引
==尽量利用一两个复杂的多字段联合索引,抗下你80%以上的 查询,然后用一两个辅助索引抗下剩余20%的非典型查询,保证你99%以上的查询都能充分利用索引,就能保证你的查询速度和性能!==
索引优化方案
- 强制使用索引
force index
(xxxxx索引名)
1 | select * from t1 force index(index_category) where r1='xx' and r2='xx' order by id desc limit xx,xx |