重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在实际开发中使用数据库时,难免会遇到一些大表数据,对这些数据进行查询时,有时候SQL会查询得特别慢,这时候,有经验的老师傅会告诉你,你看一下哪几个字段查的多,加一个索引就好了。
成都创新互联是一家专注于成都网站设计、做网站与策划设计,苏尼特右网站建设哪家好?成都创新互联做网站,专注于网站建设10余年,网设计领域的专业建站公司;建站业务涵盖:苏尼特右等地区。苏尼特右做网站价格咨询:18982081108
那么,怎么合理地建立索引呢?这里分享一下我的一些经验,如有不妥之处,欢迎批评指正。
1、不要盲目建立索引 , 先分析再创建
索引虽然能大幅度提升我们的查询性能,但也要知道,在你进行增删改时,索引树也要同样地进行维护。所以,索引不是越多越好,而是按需建立。最好是在一整块模块开发完成后,分析一下,去针对大多数的查询,建立联合索引。
2、使用联合索引尽量覆盖多的条件
这是说在一个慢sql里假如有五个where ,一个 order by ,那么我们的联合索引尽量覆盖到这五个查询条件,如果有必要,order by 也覆盖上 。
3、小基数字段不需要索引
这个意思是,如果一张表里某个字段的值只有那么几个,那么你针对这个字段建立的索引其实没什么意义,比如说,一个性别字段就两种结果,你建了索引,排序也没什么意思(也就是索引里把男女给分开了)
所以说,索引尽量选择基数大的数据去建立,能最大化地利用索引
4、长字符串可以使用前缀索引
我们建立索引的字段尽量选择字段类型较小的,比如一个varchar(20)和varchar(256)的,我们在20的上面建立的索引和在256上就有明显的差距(字符串那么长排序也不好排呀,唉)。
当然,如果一定是要对varchar(256)建立索引,我们可以选择里面的前20个字符放在索引树里(这里的20不绝对,选择能尽量分辨数据的最小字符字段设计),类似这样KEY index(name(20),age,job) ,索引只会对name的前20个字符进行搜索,但前缀索引无法适用于order by 和 group by。
5、对排序字段设计索引的优先级低
如果一个SQL里我们出现了范围查找,后边又跟着一个排序字段,那么我们优先给范围查找的字段设置索引,而不是优先排序。
6、如果出现慢SQL,可以设计一个只针对该条SQL的联合索引。
不过慢SQL的优化,需要一步步去进行分析,可以先用explain查看SQL语句的分析结果,再针对结果去做相应的改进。explain的东西我们下次再讲。
PS:在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是 执行这条SQL。
我们可以通过查看索引的属性来判断创建索引的方法。
查看索引的语法格式如下:
SHOW INDEX FROM 表名 [ FROM 数据库名]
语法说明如下:
表名:指定需要查看索引的数据表名。
数据库名:指定需要查看索引的数据表所在的数据库,可省略。比如,SHOW INDEX FROM student FROM test; 语句表示查看 test 数据库中 student 数据表的索引。
示例
使用 SHOW INDEX 语句查看《MySQL创建索引》一节中 tb_stu_info2 数据表的索引信息,SQL 语句和运行结果如下所示。
mysql SHOW INDEX FROM tb_stu_info2\G
1. row
Table: tb_stu_info2
Non_unique: 0
Key_name: height
Seq_in_index: 1
Column_name: height
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.03 sec)
其中各主要参数说明如下:
参数 说明
Table 表示创建索引的数据表名,这里是 tb_stu_info2 数据表。
Non_unique 表示该索引是否是唯一索引。若不是唯一索引,则该列的值为 1;若是唯一索引,则该列的值为 0。
Key_name 表示索引的名称。
Seq_in_index 表示该列在索引中的位置,如果索引是单列的,则该列的值为 1;如果索引是组合索引,则该列的值为每列在索引定义中的顺序。
Column_name 表示定义索引的列字段。
Collation 表示列以何种顺序存储在索引中。在 MySQL 中,升序显示值“A”(升序),若显示为 NULL,则表示无分类。
Cardinality 索引中唯一值数目的估计值。基数根据被存储为整数的统计数据计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL 使用该索引的机会就越大。
Sub_part 表示列中被编入索引的字符的数量。若列只是部分被编入索引,则该列的值为被编入索引的字符的数目;若整列被编入索引,则该列的值为 NULL。
Packed 指示关键字如何被压缩。若没有被压缩,值为 NULL。
Null 用于显示索引列中是否包含 NULL。若列含有 NULL,该列的值为 YES。若没有,则该列的值为 NO。
Index_type 显示索引使用的类型和方法(BTREE、FULLTEXT、HASH、RTREE)。
Comment 显示评注。
上一篇给小伙伴们讲了关于SQL查询性能优化的相关技巧,一个好的查询SQL离不开合理的索引设计。这篇小二就来唠一唠怎么合理的设计一个索引来优化我们的查询速度,要是有不合理的地方...嗯..
当然啦,开个玩笑,欢迎小伙伴们指正!
通常情况下,字段类型的选择是需要根据业务来判断的,通常需要遵循以下几点。
下列各种类型表格内容来自菜鸟教程,权当备忘。
优化建议:
注意: INT(2)设置的为显示宽度,而不是整数的长度,需要配合 ZEROFILL 使用 。
例如 id 设置为 TINYINT(2) UNSIGNED ,表示无符号,可以存储的最大数值为255,其中 TINYINT(2) 没有配合 ZEROFILL 实际没有任何意义,例如插入数字200,长度虽然超过了两位,但是这个时候是可以插入成功的,查询结果同样为200;插入数字5时,同样查询结果为5。
而 TINYINT(2) 配合 ZEROFILL 后,当插入数字5时,实际存储的还是5,不过在查询是MySQL会在前面补上一个0,即查询出来的实际为 05 。
优化建议:
优化建议:
通常来说,考虑好表中每个字段应该使用什么类型和长度,建完表需要做的事情不是马上建立索引,而是先把相关主体业务开发完毕,然后把涉及该表的SQL都拿出来分析之后再建立索引。
尽量少建立单值索引( 唯一索引除外 ),应当设计一个或者两三个联合索引,让每一个联合索引都尽量去包含SQL语句中的 where、order by、group by 的字段,同时确保联合索引的字段顺序尽量满足SQL查询的最左前缀原则。
索引基数是指这个字段在表里总共有多少个不同的值,比如一张表总共100万行记录,其中有个性别字段,性别一共有三个值:男、女、保密,那么该字段的基数就是3。
如果对这种小基数字段建立索引的话,因为索引树中只有男、女、保密三个值,根本没法进行快速的二分查找,同时还需要回表查询,还不如全表扫描嘞。
一般建立索引,尽量使用那些基数比较大的字段,那么才能发挥出B+树快速二分查找的优势来。
在 where 和 order by 出现索引设计冲突时,是优先针对where去设计索引?还是优先针对order by设计索引?
通常情况下都是优先针对 where 来设计索引,因为通常情况下都是先 where 条件使用索引快速筛选出来符合条件的数据,然后对进行筛选出来的数据进行排序和分组,而 where 条件快速筛选出来的的数据往往不会很多。
对生产实际运行过程中,或者测试环境大数据量测试过程中发现的慢查询SQL进行特定的索引优化、代码优化等策略。
终于轮到实战了,小二最喜欢实战了。
写到这里不得不吐槽一下,这个金三银四的跳槽季节,年前提离职了,结果离职还没办完就封村整整两个礼拜了,呜呜呜...
上节小二就提到会有个很有意思的小案例,那么在疫情当下,门都出不去的日子,感觉这个例子更有意思了,咱们来讨论一下各种社交平台怎么做的用户信息搜索呢。
社交平台有一个小伙伴们都喜欢的功能,搜索好友信息,比如小二熟练的点开省份...城市..性别..年龄..身高...
咳咳咳...小二怎么可能干这种事情,小二的心里只有代码,嗯...没错,就是这样。
这个就可以说是对于用户信息的查询筛选了,通常这种表都是非常大数据量的,在不考虑分库分表的情况下,怎么通过索引配合SQL来优化呢?
通常我们在编写SQL是会写出类似如下的SQL来执行,有 where、order by、limit 等条件来查询。
那么接下来小二一个一个慢慢增加字段来分析分析,怎么根据业务场景来设计索引。
针对这种情况,很简单,设计一个联合索引 (provice, city, sex) 就完事了。
那么这时候有小伙伴就会说了,很简单啊,范围字段放最后咱还是知道的,联合索引改成 (provice, city, sex, age) 不就可以了。
嗯,是的,这么干没毛病,但是小伙伴们有没有想过有些人万一既喜欢帅哥又喜欢美女,别想歪了哈...,挺多小姐姐就既喜欢帅哥又喜欢美女的。
那么这个时候小姐姐就不搜索性别了,那么这个时候联合索引只能用到前两个字段了,那么不符合咱们的专业标准啊,咋办呢?这时候还是有办法的,咱们只需要动动小脑袋改改SQL就行了,在没有选择性别时判断一下,改成下面这样就可以了。
咋办嘞,同样往联合索引里面塞,例如 (provice, city, sex, hobby, xx, age) 。
针对这种多个范围查询的话,为了比较好的利用索引,在业务允许的情况下可以使用固定范围,然后数据库字段存储范围标识就可以了,这样就转化为了等值匹配,就可以很好地利用索引了。
例如最后登录时间字段不记录最后登录时间,而是记录设置字段 is_login_within_seven_days 在7天内有登录则为1,否则为0,最后索引设计成 (provice, city, sex, hobby, xx, is_login_within_seven_days, age) 。
那么根据场景最后设计出来的这个索引可能已经可以覆盖大部分的查询流量了,那么如果还有其他一部分热度比较高的查询怎么办呢,办法也很简单啊,再加一两个索引即可。
例如通常会查询这个城市比较受欢迎(评分:score)的小姐姐,这时候添加一个联合索引 (provice, city, sex, score) 那么就可以了。
可以看出,索引时必须结合场景来设计的,思路就是尽量用不超过3个复杂的联合索引来抗住大部分的80%以上的常用查询流量,然后再用一两个二级索引来抗下一些非常用查询流量。
以上就是小二要给大家分享的索引设计,如果能动动你发财的小手给小二点个免费的赞就更好啦~
下篇小二就来讲讲MySQL事务和锁机制。