设计索引的时候,我们一般要考虑哪些因素

一、
首先,我们在针对业务需求建立好一张表的结构之后,就知道这个表有哪些字段,每个字段是什么类型的,会包含哪些数据 接着设计好表结构之后,接下来要做的,就是要设计表的索引,这个设计索引的时候,我们要考虑第一点,就是未来我们对表进行查询的时候,大概会如何来进行查询?

其实很多时候很多人可能说,你要让我刚设计完表结构就知道未来会怎么查询表,那我怎么可能知道呢,实在是想不出来!

好,那么没关系,此时我们完全可以在表结构设计完毕之后,先别急着设计索引,因为此时你根本不知道要怎么查询表。

接着我们就可以进入系统开发的环节,也就是说根据需求文档逐步逐步的把你的Java业务代码给写好,在写代码的过程中,现在一般我们都是用MyBatis作为数据持久层的框架的,你肯定会写很多的MyBatis的DAO和Mapper以及SQL吧?那么当你系统差不多开发完毕了,功能都跑通了,此时你就可以来考虑如何建立索引了,因为你的系统里所有的MyBatis的SQL语句都已经写完了,你完全知道对每一张表会发起些什么样的查询语句,对吧?

那么这个时候,第一个索引设计原则就来了,针对你的SQL语句里的where条件、order by条件以及group by条件去设计索引也就是说,你的where条件里要根据哪些字段来筛选数据?order by要根据哪些字段来排序?group by要根据哪些字段来分组聚合?

此时你就可以设计一个或者两三个联合索引,每一个联合索引都尽量去包含上你的where、order by、group by里的字段,接着你就要仔细审查每个SQL语句,是不是每个where、order by、group by后面跟的字段顺序,都是某个联合索引的最左侧字段开始的部分字段?

比如你有一个联合索引是INDEX(a,b,c),此时你一看发现有三个SQL,包含了where a =? and b=?,order by a,b,group by a这些部分,那么此时where、order by、group by后续跟的字段都是联合索引的最左侧开始的部分字段,这就可以了,说明你的每个SQL语句都会用上你的索引了。

所以在设计索引的时候,首先第一条,就是要按照这个原则,去保证你的每个SQL语句的where、 order by和group by都可以用上索引。

二、
在设计索引的时候还得考虑其他的一些问题,

首先一个就是字段基数问题,举个例子,有一个字段他一共在10万行数据里有10万个值对吧?结果呢?这个10万值,要不然就是0,要不然就是1,那么他的基数就是2,为什么?因为这个字段的值就俩选择,0和1。

假设你要是针对上面说的这种字段建立索引的话,那就还不如全表扫描了,因为你的索引树里就仅仅包含0和1两种值,根本没法进行快速的二分查找,也根本就没有太大的意义了,所以这种时候,选用这种基数很低的字段放索引里意义就不大了。
一般建立索引,尽量使用那些基数比较大的字段,就是值比较多的字段,那么才能发挥出B+树快速二分 查找的优势来。

其次的话,你尽量是对那些字段的类型比较小的列来设计索引,比如说什么tinyint之类的,因为他的字段类型比较小,说明这个字段自己本身的值占用磁盘空间小,此时你在搜索的时候性能也会比较好一点。

不过当然了,这个所谓的字段类型小一点的列,也不是绝对的,很多时候你就是要针对varchar(255)这 种字段建立索引,哪怕多占用一些磁盘空间,那你也得去设计这样的索引,比较关键的其实还是尽量别把基数太低的字段包含在索引里,因为意义不是太大。

那当然了,万一要是你真的有那种varchar(255)的字段,可能里面的值太大了,你觉得都放索引树里太占据磁盘空间了,此时你仔细考虑了一下,发现完全可以换一种策略,也就是仅仅针对这个 varchar(255)字段的前20个字符建立索引,就是说,对这个字段里的每个值的前20个字符放在索引树里而已。

此时你建立出来的索引其实类似于KEY my_index(name(20),age,course),就这样的一个形式,假设 name是varchar(255)类型的,但是在索引树里你对name的值仅仅提取前20个字符而已。

此时你在where条件里搜索的时候,如果是根据name字段来搜索,那么此时就会先到索引树里根据 name字段的前20个字符去搜索,定位到之后前20个字符的前缀匹配的部分数据之后,再回到聚簇索引提取出来完整的name字段值进行比对就可以了。

但是假如你要是order by name,那么此时你的name因为在索引树里仅仅包含了前20个字符,所以这个排序是没法用上索引了!group by也是同理的。

三、

首先假设你设计好了一个索引,非常棒,接着你在SQL里这么写:where function(a) = xx,你给你的索引里的字段a套了一个函数,你觉得还能用上索引吗?
明显是不行了。所以尽量不要让你的查询语句里的字段搞什么函数,或者是搞个计算。

现在设计索引的时候需要注意的点都已经讲完了,其实就是好好设计索引,让你的查询语句都能用上索引,同时注意一下字段基数、前缀索引和索引列套函数的问题,尽量让你的查询都能用索引,别因为一 些原因用不上索引了。

接着我们来看看索引设计好之后,接着你系统跑起来,有数据插入也有查询的情况,其实查询基本都能走索引一般问题都不会太大的,但是插入就有点讲究了,之前也跟大家说过,其实你插入数据的时候, 他肯定会更新索引树。

你插入数据肯定有主键吧,那有主键就得更新聚簇索引树,你插入一条数据肯定会包含索引里各个字段的值吧,那你的联合索引的B+树是不是也要更新?

对了,你不停的增删改数据,就会不停的更新你的索引树。

所以因为你插入的数据值可能根本不是按照顺序来的,很可能会导致索引树里的某个页就会自动分裂, 这个页分裂的过程就很耗费时间,因此一般让大家设计索引别太多,建议两三个联合索引就应该覆盖掉你这个表的全部查询了。

否则索引太多必然导致你增删改数据的时候性能很差,因为要更新多个索引树。 另外很关键一点,建议大家主键一定是自增的,别用UUID之类的,因为主键自增,那么起码你的聚簇索引不会频繁的分裂,主键值都是有序的,就会自然的新增一个页而已,但是如果你用的是UUID,那么也会导致聚簇索引频繁的页分裂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值