Mysql建立索引经验

Mysql建立索引经验,第1张

在实际开发中使用数据库时,难免会遇到一些大表数据,对这些数据进行查询时,有时候SQL会查询得特别慢,这时候,有经验的老师傅会告诉你,你看一下哪几个字段查的多,加一个索引就好了。

那么,怎么合理地建立索引呢?这里分享一下我的一些经验,如有不妥之处,欢迎批评指正。

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。

索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引。MyISAM和InnoDB存储引擎:只支持BTREE索引,也就是说默认使用BTREE,不能够更换,MySQL5.7中InnoDB可以支持HASH索引;MEMORY/HEAP存储引擎:支持HASH和BTREE索引。索引可划分为单列索引(其中包括普通索引、唯一索引、主键索引)、组合索引、全文索引、空间索引,其中单列索引是一个索引只包含单个列,但一个表中可以有多个单列索引。

MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。

索引列中的值必须是唯一的,但是允许为空值,

是一种特殊的唯一索引,不允许有空值。

在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。

由id、name和age3个字段构成的索引,索引行中就按id/name/age的顺序存放,索引可以索引下面字段组合(id,name,age)、(id,name)或者(id)。如果要查询的字段不构成索引最左面的前缀,那么就不会是用索引,比如,age或者(name,age)组合就不会使用索引查询

全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引。全文索引就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个大牛,神人 ..." 通过大牛,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节,我们只需要知道这个大概意思。

只有在MyISAM引擎上才能使用,空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。

在创建空间索引时,使用SPATIAL关键字。

创建空间索引的列,必须将其声明为NOT NULL。。

SPATIAL INDEX spatIdx(g)

全值匹配我最爱,最左前缀要遵守;

带头大哥不能死,中间兄弟不能断;

索引列上少计算,范围之后全失效;

Like百分写最右,覆盖索引不写星;

不等空值还有or,索引失效要少用;

VAR引号不可丢,SQL高级也不难!

参考: <u>https://blog.csdn.net/zjy15203167987/article/details/81812370</u>

参考: <u>https://www.jianshu.com/p/d5b2f645d657</u>

如果索引包含满足查询的所有数据,就称为覆盖索引。覆盖索引是一种非常强大的工具,能大大提高查询性能。只需要读取索引而不用读取数据有以下一些优点:

(1) 索引项通常比记录要小,所以MySQL访问更少的数据;

(2) 索引都按值的大小顺序存储,相对于随机访问记录,需要更少的I/O;

(3) 大多数据引擎能更好的缓存索引。比如MyISAM只缓存索引。

(4) 覆盖索引对于InnoDB表尤其有用,因为InnoDB使用聚集索引组织数据,如果二级索引中包含查询所需的数据,就不再需要在聚集索引中查找了。

覆盖索引不能是任何索引,只有B-TREE索引存储相应的值。而且不同的存储引擎实现覆盖索引的方式都不同,并不是所有存储引擎都支持覆盖索引(Memory和Falcon就不支持)。

对于索引覆盖查询(index-covered query),使用EXPLAIN时,可以在Extra一列中看到“Using index”。

产品中有一张图片表,数据量将近100万条,有一条相关的查询语句,由于执行频次较高,想针对此语句进行优化。表结构很简单,主要字段:

user_id 用户ID

picname 图片名称

smallimg 小图名称

一个用户会有多条图片记录,现在有一个根据user_id建立的索引:uid,查询语句也很简单。取得某用户的图片集合

执行查询语句(为了查看真实执行时间,强制不使用缓存)

执行了10次,平均耗时在40ms左右。使用explain进行分析

使用了user_id的索引,并且是const常数查找,表示性能已经很好了

因为这个语句太简单,sql本身没有什么优化空间,就考虑了索引。修改索引结构,建立一个(user_id,picname,smallimg)的联合索引:uid_pic。重新执行10次,平均耗时降到了30ms左右。使用explain进行分析

看到使用的索引变成了刚刚建立的联合索引,并且Extra部分显示使用了'Using Index'

'Using Index'的意思是“覆盖索引”,它是使上面sql性能提升的关键。一个包含查询所需字段的索引称为“覆盖索引”,MySQL只需要通过索引就可以返回查询所需要的数据,而不必在查到索引之后进行回表 *** 作,减少IO,提高了效率。

例如上面的sql,查询条件是user_id,可以使用联合索引,要查询的字段是picname smallimg,这两个字段也在联合索引中,这就实现了“覆盖索引”,可以根据这个联合索引一次性完成查询工作,所以提升了性能

InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面带来的性能损耗可能比表级锁定要更高一些,但是在整体并发处理能力方面是要远远优于MyISAM的表级锁定的。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显的优势了。但是当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不比MyISAM高,甚至可能会更差。

建议:

(1)尽可能让所有的数据检索都通过索引来完成,从而避免InnoDB因为无法通过索引键加锁而升级为表级锁定

(2)合理设计索引,让InnoDB在索引键上面加锁的时候尽可能准确,尽可能地缩小锁定范围,避免造成不必要的锁定而影响其他Query的执行

(3)尽可能减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录

(4)尽量控制事务的大小,减少锁定的资源量和锁定时间长度

(5)在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少MySQL因为实现事务隔离级别所带来的附加成本。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7354576.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-04
下一篇 2023-04-04

发表评论

登录后才能评论

评论列表(0条)

保存