Mysql的索引是什么?如何创建索引?创建索引的原则?怎么优化?

索引的理解:

  索引是对数据库表中的一列或多列的值进行排序的一种数据结构。
  索引的作用就类似于书本的目录,新华字典的拼音,偏旁部首的首查字,可以快速的检索到需要的内容,mysql在300万条记录性能就下降了,虽然mysql官方文档说达500万~800万,所以当数据达到几百万的时候,那么索引就很有必要了。
  当表中有大量记录的时候,若要对表进行查询,第一种就是就需要把表中的记录全部取出来,在和查询条件一一对比,然后返回满足条件的记录、这样做就会大大消耗数据库系统的时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中ROWID(相当于页码)快速找到表中的记录。

语句:

CREATE TABLE table_name[filed_name data type]
[unique|fulltext][index|key][index_name](filed_name[length])[asc|desc]

  1. unique|fulltext为可选参数,分别表示唯一索引、全文索引
  2. index和key为同义词,两者作用相同,用来指定创建索引
  3. filed_name为需要创建索引的字段列,该列必须从数据表中该定义的多个列中选择
  4. index_name指定索引的名称,为可选参数,如果不指定,默认filed_name为索引值
  5. length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度
  6. asc或desc指定升序或降序的索引值存储

索引类型:

一、唯一索引(unique):列的值必须唯一,但允许有空值。如果是组合索引则列值必须唯一

1)、创建唯一索引

CREATE UNIQUE INDEX index_name ON table(column(length))

2)、修改表结构

ALTER TABLE table_name ADD UNIQUE INDEX index_name ON (column(length))

3)、创建表时直接指定

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`code` INT(8) NOT NULL,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
UNIQUE index_name(code)
);

二、主键索引(primary key):是一特殊的唯一索引,一个表允许有一个主键,主键要求建表时指定.

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`code` INT(8) NOT NULL,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
PRIMARY KEY(`id`)
);

三、普通索引(index):最基本的索引,没有任何限制。如果是char,varchar类型,length可以小于字段长度、如果是BLOB和TEXT类型,必须指定长度。

1)、直接创建

CREATE INDEX index_name ON table(column(length))

2)、修改表结构的方式添加

ALTER TABLE table_name ADD INDEX index_name ON (column(length))

3)、创建表时直接指定

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
PRIMARY KEY(`id`),
INDEX index_name(title(length))
);

4)、删除索引

DROP INDEX index_name ON table

四、多列索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段索引才会使用。使用组合索引遵循最左前缀原则
五、全文索引(fulltext):主要是用来查找文本的关键字,而不是直接与索引中的值比较。fulltext索引跟其他索引大不相同,它更像一个搜索引擎,而不是简单的where语句的参数匹配。fulltext要配合match against操作使用,而不是一般的where语句加like。它可以在create tablealter tablecreate index使用,不过目前只有char varchar text列上可以创建全文索引。

tip:全文索引只有MyISAM支持,不过在mysql5.6后Innodb也支持了

1)、创建表的时候添加全文索引


CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
FULLTEXT (content)
);

2)、修改表结构添加全文索引

ALTER TABLE table_name ADD FULLTEXT index_name(content)

3)、直接创建索引

CREATE FULLTEXT INDEX index_namet ON table_name(content)

缺点:

  1. 虽然索引大大的提升了查询的速度,同时也降低了对表的增删改的速度,因为更新表,不仅要保存数据,还要保存索引文件
  2. 建立索引会占用磁盘空间。一般不太严重,如果你在一个大表上创建多种组合索引,索引文件会增长很快索引只是提高效率的一个因素,如果有大数据量的表,就要花时间研究建立最优秀的索引,或优化查询语句

索引方式:

    对于BTREE和HASH索引,当使用=、<=>、IN、IS NULL或者IS NOT NULL操作符时,关键元素与常量值的比较关系对应一个范围条件。Hash索引还有一些其它特征:它们只用于使用=或<=>操作符的等式比较(但很快)。优化器不能使用hash索引来加速ORDER BY操作。(该类索引不能用来按顺序搜索下一个条目)。MySQL不能确定在两个值之间大约有多少行(这被范围优化器用来确定使用哪个索引)。如果你将一个MyISAM表改为hash-索引的MEMORY表,会影响一些查询。只能使用整个关键字来搜索一行。(用B-树索引,任何关键字的最左面的前缀可用来找到行)。

    对于BTREE索引,当使用>、<、>=、<=、BETWEEN、!=或者<>,或者LIKE ‘pattern’(其中 ‘pattern’不以通配符开始)操作符时,关键元素与常量值的比较关系对应一个范围条件。“常量值”系指:查询字符串中的常量、同一联接中的const或system表中的列、无关联子查询的结果、完全从前面类型的子表达式组成的表达式。

下面是一些WHERE子句中有范围条件的查询的例子。
下列范围查询适用于 btree索引和hash索引:

SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20);

下列范围查询适用于btree索引

SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10;
SELECT * FROM t1 WHERE key_col LIKE 'ab%' OR key_col BETWEEN 'bar' AND 'foo';

创建索引原则与使用索引注意事项:

  1. 选择唯一索引

    唯一索引的值是唯一的,可以更快速的通过该索引确定某一条记录

  2. 为经常需要排序、分组和联合操作的字段建立索引

    经常需要order by、 group by、distinct和union等操作的字段,排序会浪费很多时间,如果为其建立索引,可以有效避免排序操作

  3. 经常作为查询条件的字段建立索引

    如果某个字段经常作为查询条件,name该字段的查询速度就会影响整个表的速度。因此,为这样的字段建立索引,可以提高整个表的查询速度

  4. 限制索引的数目

    索引的数目不是越多越好。每个索引都是要占用磁盘空间的,索引越多,需要的磁盘空间就越大。修改表时,和更新会很麻烦。越多的索引,会使更新表变得很浪费时间

  5. 尽量使用数据量少的索引

    如果索引的值很长,那么查询的速度就会受到影响,例如对一个char(100)类型的字段进行全文检索需要的时间肯定要比char(10)类型的字段需要的时间多得多,并且char(10)全文检索而且可以节省磁盘空间和I/O操作。

  6. 尽量使用前缀来索引

    如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。

  7. 删除不再使用或者很少使用的索引

    表中的数据被大量更新,或者数据使用方式被改变后,原有的一些索引可能不在需要。数据库管理员应当定期找出这些索引,将它们删除。从而减少索引对更新操作的影响

  8. 最左前缀原则,非常重要的一个原则

    mysql会一直向右匹配知道遇到范围查询(>、<、between、like)就停止匹配,比如a=1 and b=2 and c>3 and d=4 如果建立(a,b,c,d)顺序索引,d是用不到索引的,如果是建立(a,b,d,c)则可以都用到

  9. =和in可以乱序

    比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

  10. 尽量选择区分度高的列作为索引。

    区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就 是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条 记录

  11. 索引列不能参与计算,保持列“干净”。

    select * from users where YEAR(adddate)<'2007';
    将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:
    select * from users where adddate<‘2007-01-01';

  12. 尽量的扩展索引,不要新建索引。

    比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可

  13. 不使用NOT IN和<>操作

  14. like语句操作

    一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

  15. 索引列排序

    MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

  16. 索引不会包含有NULL值的列

    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。


注意:选择索引的最终目的是为了使查询的速度变快。上面给出的原则是最基本的准则,但不能拘泥于上面的准则。读者要在以后的学习和工作中进行不断的实践。根据应用的实际情况进行分析和判断,选择最合适的索引方式。

索引优化:

一、导致SQL执行慢的原因

  1. 硬件问题。如网络速度慢,内存不足,I/O吞吐量少,磁盘空间满了等。
  2. 没有索引或索引失效。
  3. 数据过多(分库分表)。
  4. 服务器调优及各个参数设置(调整my.cnf)

二、分析原因时,一定要找切入点

  1. 先观察,开启慢查询日志,设置相应的阈值(比如超过2秒就是慢SQL),在生产环境上跑一天以后,看看那些SQL比较慢
  2. Explain和慢SQL分析。比如写的烂的SQL语句,索引没有或失效,关联查询太多(有时候是设计缺陷或者不得已的需求)等等
  3. Show Profile是比Explain更进一步的执行细节,可以查询到每一个SQL都干了些什么事,这些事分别花了多少时间
  4. 找DBA或运维对MYsql进行服务器参数调优

Explain 与 Show Profile详情下两章介绍

参考:https://blog.csdn.net/GV7lZB0y87u7C/article/details/79969293
   https://blog.csdn.net/u013412790/article/details/51612304

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章