勿以恶小而为之,勿以善小而不为--------------------------刘备

上一章简单介绍了 MySQL的视图(二十二),如果没有看过,请观看上一章

一. 索引

一.一 索引的产生

前面已经学习了查询,有没有想过这样一个问题? 数据库表是如何查询的呢?
自然是从第一条记录到最后一条记录,依次遍历,看条件是否符合,如果符合,就展示出来,
如果不符合,就继续遍历,直到末尾。

如 从 user 表里面查询 id=5 的员工记录,

 select * from user where id=5;

会先从 user 表的开头 id=1 处时开始遍历,遍历到id=4时,发现不符合条件,那么继续遍历,
到id=5了,发现id=5符合条件,就将这一条记录展示出来。
由于id是主键,只存在唯一一条记录,那么就不继续往下面遍历了。

如果 从user 表里面查询 name=‘岳泽霖’ 的员工记录. (岳泽霖的员工编号 id是5)

 select * from user where name='岳泽霖';

会先从 user 表的开头 id=1处时开始遍历,查询id=1时的name名称,看是否符合条件为 ‘岳泽霖’,
发现不符合条件,继续遍历。 遍历到id=4时,也不符合条件,继续遍历。
到id=5时,该条记录的name 是 ‘岳泽霖’,符合条件,就将这一条记录展示出来。
由于 name并不是主键,也不是唯一约束,可能存在多个值,所以会继续往下面遍历,
发现id=6,id=7,直到最后,也没有找到其他的记录,所以共展示出一条记录, id=5的记录。
(注意: id=6,id=7… 继续查询了)

查询,类似于算法中的搜索, 不同的搜索算法,查询的时间和所需要的空间是不同的。
很明显,上面的这种数据库查询方式不太友好,特别是数据量大的时候。
假如,user 表有三百万条数据, 要查询最后一条记录, 需要将前面的 (三百万-1) 条数据先查询后判断一下,
最后才能得出一条。如果 要查询的记录不存在, 那么将所有的三百万条数据查询判断之后,
发现没有对应的数据,得到 null, 也是不太友好的。
实际生活和工作中,数据量远远大于三百万,尤其是目前大数据的年代。 所以,会导致查询的速度更慢。

不知道有没有观察过字典,字典前面常常有几十页,是拼音索引,笔画索引,部首索引等,
利用索引,可以很方便的定位到数据库中的记录。

MySQL数据库就支持索引。 索引主要是为了提高查询速度,缩短查询的时间。

一.二 索引的实际效果

老蝴蝶先在数据库 yuejl 中创建了一个表 myindex, 用于存放大量数据。

myindex 表里面, 有 id (主键),name,name_cp(与name查询时,进行比较,数据完全一样) 三个字段。

 show create table myindex \G

通过 java 的批处理程序,已经插入了将近三百万条数据, 形式为 (i,两个蝴蝶飞i,两个蝴蝶飞i)

由于 id是主键,隐含了唯一索引,用 name 和 name_cp 字段来进行演示。

演示一:

分别查询 name 为 20000000 (二百万) 和 2999999 (三百万-1) 的时间。

然后,为 name 添加索引,再搜索 name为 2000000 和 2999999 的时间。

观察,前后时间的对比。

 // 添加索引之前select * from myindex where name='两个蝴蝶飞2000000';select * from myindex where name='两个蝴蝶飞2999999';//添加索引create index index_name on myindex(name);//添加索引之后,再次进行查询select * from myindex where name='两个蝴蝶飞2000000';select * from myindex where name='两个蝴蝶飞2999999';

未创建索引之前, 查询 2000000的时间大约是 0.77s, 2999999的时间大约是 0.90s,

而创建索引之后, 查询2000000的时间大约是0.00s, 2999999的时间大约也是 0.00s, 忽略成 瞬查。

(每一次查询的最终时间,并不是一样的,受内存等因素的影响)

注意,为已经存在了大量数据的表添加索引时,花费时间很长。 本次演示花费了 10s以上。

接下来, 重新删除掉索引, 为 name_cp 添加索引进行演示。

 alter table myindex drop index index_name;


演示二:

name和 name_cp的数据,完全一样。

 // 添加索引之前 name的查询select * from myindex where name='两个蝴蝶飞2000000';select * from myindex where name='两个蝴蝶飞2999999';// 添加索引之前 name_cp的查询select * from myindex where name_cp='两个蝴蝶飞2000000';select * from myindex where name_cp='两个蝴蝶飞2999999';//添加索引 为 name_cpcreate index index_name_cp on myindex(name_cp);//添加索引之后,name进行查询select * from myindex where name='两个蝴蝶飞2000000';select * from myindex where name='两个蝴蝶飞2999999';//添加索引之后,name_cp进行查询select * from myindex where name_cp='两个蝴蝶飞2000000';select * from myindex where name_cp='两个蝴蝶飞2999999';

每次查询结果的时间通常是不一样的,但添加了索引之后,也同样达到了 瞬查的效果。

用 id (隐含了 唯一索引) 进行查询的话:

 select * from myindex where id=2000000;select * from myindex where id=2999999;

发现,索引可以大大的缩短查询的时间。

在前台页面时,查询数据用了1s,处理数据用了0.5s, 那么用户共延时 1.5s, 用户会感觉到卡。
而用了索引之后,查询数据用了0.00s,处理数据用了0.5s (实际开发中,后端程序逻辑也会优化) ,
那么用户共延时 0.5s, 用户不会感觉到很卡。

一.三 索引的优缺点

索引是在存储引擎中实现的,与数据表的存储引擎有关。 每一种的存储引擎的索引都不一定完全相同,
每一种存储引擎也不一定支持所有的索引类型。

目前的索引类型有两种: BTREE 和 HASH.

MyISAM 和 InnoDB 存储引擎只支持 BTREE . MEMORY/HEAP 支持 BTREE 和 HASH.

通常的常见存储引擎为 MyISAM 和 InnoDB, 5.7版本默认的存储引擎是 InnoDB. 需要掌握 BTREE.

优点:

  1. 大大加快数据的查询速度 ,是最主要的原因
  2. 通过创建唯一索引,可以保证每一行数据的唯一性。
  3. 对于外键的字段,添加索引,可以加速表和表之间的连接。
  4. 对于分组和排序的字段添加索引,也可以减少分组和排序的时间.

缺点:

  1. 创建索引和维护索引要花费时间,并且随着数据量的增加,花费的时间也增加。
  2. 索引需要占磁盘空间,如果有大量的索引,可以索引文件与数据文件还大。
  3. 当对表数据进行维护(插入,更新,删除)时,索引也要动态的维护,降低了数据的维护速度。

一.四 索引的分类

索引可以分为以下几类

一.四.一 普通索引和唯一索引

普通索引是默认索引, 允许插入重复值和空值。

唯一索引,索引值必须唯一,但允许是空值。类似于 UNIQUE 约束(修改表结构的 唯一约束,是对索引的维护)。
如果是组合索引,那么组合的值,必须唯一。

其中,主键索引是一种特殊的唯一索引,只是不允许有空值。

创建表时,设置主键, 隐含了唯一索引。

一.四.二 单列索引和组合索引

单列索引只包含单个列, 组合索引包含了两个及两个以上的列。
(name) 是单列索引, (name,name_cp) 是多列索引。

注意,多列索引时,需要遵循最左前缀原则

即: (name,name_cp) 组合索引时, where 条件 是name_cp ,没有name的话,是不能用索引的。

(name,name_cp,age) 组合索引时, where条件是 name_cp和age,没有 name的话,是不能用索引的。

(name,name_cp,age) 组合索引时, where 条件是 name,age的话,是可以用索引的。

组合索引时,要注意各个列的顺序,要将查询时最常用的列放置在左边。

一.四.三 全文索引

全文索引是 FULLTEXT . 支持全文查找,可以重复,也可以为空值。 通常在 CHAR,VARCHAR,TEXT上创建。

注意,只有 MyISAM存储引擎才支持全文索引 (ps:实际操作中,5.6版本之后 ,InnoDB也支持)

一.四.四 空间索引

只能在空间数据类型上使用。 空间数据类型有 GEOMETRY,POINT,LINESTRING 和 POLYGON.

不允许有空值。 只有 MyISAM 存储引擎才支持空间索引 (ps:不常用,5.7.4版本之后,InnoDB也支持)

一.五 索引的设计原则

索引设计的不合理,或者缺少索引,都可能会对性能造成相应的影响。 高效的索引,才是重要的。

  1. 索引并非越多越好
  2. 数据量小的表最好不使用索引
  3. 查询中很少使用的列或者参考的列,不使用索引
  4. 只有很少数据值的列,不应该使用索引。 如 性别列,学历列。
  5. 对于经常更新的表,避免使用索引, 对于经常查询的列,使用索引。

二. 创建索引

创建索引时,可以在创建表的同时,创建索引, 也可以在已经存在的表上创建索引。
注意,对于已经存在的表,要注意表数据对索引的影响。 如表中有相同的数据,那么是不能创建唯一索引的。

只讲解 最常见的 普通索引 和唯一索引。 组合索引,在文章最后讲解。

全文索引,空间索引,用得较少,只在文章最后简单讲述一下。

二.一 在创建表的同时,创建索引

二.一.一 创建命令

命令:

 create table table_name [col_name data_type][空|unique|fulltext|spatial] index index_name (col_name [length]) [asc|desc]

index_name 如果不指定,默认col_name 为索引值。 通常情况下,建议指定。

length 为索引的长度,只有字符串类型才能指定索引长度.

二.一.二 普通表的创建,用于比较区别

如创建一个 noIndex 表, 里面只有 id,name 和 age 三个字段。

 // 创建表create table noIndex(id int(11) primary key,name varchar(20),age int(3));// 展示表信息show create table noIndex \G

二.一.三 创建普通索引

创建 一个 index1 表, 在 name 上创建 索引。 名称 为 index1_name

// 创建表create table index1(id int(11) primary key,name varchar(20),age int(3),index index1_name(name));// 展示表信息show create table index1 \G

说明,索引创建成功。

二.一.四 查看索引是否正在使用

查看 索引是否正在使用, 用 explain 。 关于 explain 的用法,后面老蝴蝶会讲解的。

在name 上创建了索引:

 explain select * from index1 where name='两个蝴蝶飞' \G

possible_keys 和 key 均为 index1_name, 表示使用了 索引。

在 age 上没有创建索引:

 explain select * from index1 where age=24 \G

possible_keys 和 key 为 null, 表示 没有使用索引。

二.一.五 show index from 表名 查看索引信息

可以通过 show index from 表名, 来查看当前表 的索引信息

 select index from index1;

参数 说明
Table 创建索引的表名
Non_unique 索引 非唯一索引吗?, 1 表示 非唯一索引,0表示 唯一索引
Key_name 索引的名称, 主键的话,是 PRIMARY
Seq_in_index 列在索引中的位置,如果是单列索引,那么是1,组合索引,为每个字段在索引中定义的顺序
Column_name 定义索引的列字段
Collation 何种顺序存储在索引中。 A 表示升序 (默认,ASC), null 表示无分类
Cardinality 索引中唯一值数目的估计值。基数根据被存储为整数的统计数据计数,
所以即使对于小型表,该值也没有必要是精确的。
基数越大,当进行联合时,MySQL 使用该索引的机会就越大
Sub_part 索引的长度。 字符串类型时,展示长度,不是字符串类型,为null
Packed 指示关键字如何被压缩。若没有被压缩,值为 NULL
Null 用于显示索引列中是否包含 NULL。若列含有 NULL,该列的值为 YES。
若没有,则该列的值为 NO
Index_type 索引的类型, 有BTREE 和 HASH两种
Comment 评注,注释
Index_comment 索引的评注

二.一.六 创建唯一索引

创建一个 index2表,在 name 上创建唯一索引,名称为 index2_name

 // 创建表create table index2(id int(11) primary key,name varchar(20),age int(3),unique index index2_name(name(20)));// 展示表信息show create table index2 \G

插入重复数据,验证一下 唯一索引起作用了

 insert into index2 values(1,'两个蝴蝶飞',24);select * from index2;insert into index2 values(2,'两个蝴蝶飞',25);

唯一索引,起作用了。

二.二 在已经存在的表上创建索引

二.二.一 alter table 表名 创建索引

命令:

 alter table 表名  add [空|UNIQUE|FULLTEXT\SPATIAL] index [index_name] (col_name (length)) [ASC|DESC]

最开始的 noIndex 表是没有索引的。

操作1: 给这个表的 age 字段 添加 普通索引

 alter table noIndex add index noIndex_age (age) ;

操作2: 给这个表的 name 字段 添加 唯一索引

 alter table noIndex add index noIndex_name (name(20)) ;

查看一下,当前的索引

 show create table noIndex \G

添加索引成功。

二.二.二 create index index_name on 表名 (列名) 创建索引

命令:

 create [空|unique|fulltext|spatial] index index_nameon table_name (col_name(length)) [ASC|DESC]

操作1: 给 index2 表的 age 创建普通索引

 create index index2_ageon index2 (age);

操作2: 给 index1 表的 age 创建唯一索引

 create  unique index index1_ageon index1 (age);

三. 删除索引

与 创建索引的后两种方式对应,删除索引,也有相对应的方式 .

三.一 alter table 表名 drop index 索引名

注意,这个 index 是单独的index, 表示索引的意思。

只根据 索引名称进行删除。 这也是创建索引时,建议自定义索引名的原因。

操作1: 删除 noIndex 表的 唯一索引 索引名为 noIndex_name

 alter table noIndex drop index noIndex_name;

三.二 drop index 索引名 on 表名

操作1: 删除 noIndex 表的普通索引,索引名为 noIndex_age

 drop index noIndex_age on noIndex;

四. 索引的补充

不常用,仅作为一个补充。

四.一 创建 单列索引

创建 index3 表,name 为单列索引

 // 创建表create table index3(id int(11) primary key,name varchar(20),age int(3),index index3_name(name(20)));// 展示表信息show create table index3 \G

四.二 创建组合索引

创建 index4 表,name ,age 为组合索引

 // 创建表create table index4(id int(11) primary key,name varchar(20),age int(3),index index4_name(name(20),age));// 展示表信息show create table index4 \G

要注意,需要遵循 最左前缀原则。

如 单独查询 age 是不能触发索引的

possible_keys 是 null

查询 name 和 age 是可以触发的

单独查询 name 也是可以触发的。

四.三 创建 全文索引

创建表 index5, name 为全文索引

 // 创建表create table index5(id int(11) primary key,name varchar(20),age int(3),fulltext index index5_name(name(20)));// 展示表信息show create table index5 \G

发现,引擎为 InnoDB ,也没有报错。

如果版本低,不支持,那么创建时,可以在创建表时,指定引擎

 // 创建表create table index7(id int(11) primary key,name varchar(20),age int(3),fulltext index index7_name(name(20))) engine=MyISAM;// 展示表信息show create table index7 \G

四.四 创建 空间索引

创建表为 index6, 数据类型必须为那四种的一种

 create table index6(id int(11) primary key,name geometry not null,age int(3),spatial index index6_name(name));show create table index6 \G

如果版本低,不支持,那么创建时,可以在创建表时,指定引擎

 create table index8(id int(11) primary key,name geometry not null,age int(3),spatial index index8_name(name)) engine=MyISAM;show create table index8 \G

索引非常重要,需要掌握。

谢谢!!!

MySQL的索引(二十三)相关推荐

  1. mysql 唯一索引 二叉法_mysql 唯一索引

    1.一个列的唯一索引 mysql> create database pay; Query OK, 1 row affected (0.03 sec) mysql> use pay; Dat ...

  2. mysql覆盖索引二次查找_mysql中关于覆盖索引的知识点总结

    如果一个索引包含(或覆盖)所有需要查询的字段的值,称为'覆盖索引'. 覆盖索引是一种非常强大的工具,能大大提高查询性能,只需要读取索引而不需要读取数据,有以下优点: 1.索引项通常比记录要小,所以My ...

  3. 夜光带你走进C# winform 操作mysql数据库(二十三)擅长的领域

    夜光序言: 梦里常出现的人,醒来就应该去见他. 正文:

  4. MySQL优化(二):索引的类型、匹配原则、创建原则

    目录 索引的优缺点 索引类型 聚簇索引(主键索引) 非聚簇索引(二级索引.辅助索引) 索引匹配的原则 最左匹配原则 无法使用索引的场景 索引创建的原则 使不使用索引的依据到底是什么? 参考 索引的优缺 ...

  5. 零基础带你学习MySQL—primary key主键(二十三)

    零基础带你学习MySQL-primary key主键(二十三) 一.约束 二.主键 三.主键的细节说明 主键不能重复而且不能为空 一张表最多只能有一个主键,但可以是复合键 使用desc 表名 可以看到 ...

  6. mysql 索引 二_MySQL之索引(二)

    高性能的索引策略 正确地创建和使用索引是实现高性能查询的基础.在MySQL之索引(一)这一章中我们介绍了各种类型的索引及其对应的优缺点.现在我们一起来看看如何真正地发挥这些索引的优势. 独立的列 我们 ...

  7. 为了把mysql的索引底层原理讲清楚,我把计算机翻了个底朝天

    来自:非科班的科班 什么是索引 概念:索引是提高mysql查询效率的数据结构.总的一句话概括就是索引是一种数据结构. 数据库查询是数据库的最主要功能之一.设计者们都希望查询数据的速度能尽可能的快,因此 ...

  8. mysql单列索引和多列索引_浅谈MySQL索引优化

    索引基础知识总结及常见索引优化手段 一.索引简介 什么是索引? MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构. 可以简单理解为"排好序的快速查找数据 ...

  9. mysql+零时数据结构,MySql主要索引数据结构

    索引数据结构 1. 二叉搜索树(Binary Search Tree) 二叉搜索树是每个节点最多有两个子节点的树,按照右侧子节点大于本节点,左侧子节点小于本节点的规律排列,可以用作搜索,结构如下图所示 ...

最新文章

  1. iis5.1配置php5.3.1详解,WinXP IIS 5.1 PHP 5.3 VC9.0 配置详解
  2. Python Django URL逆向解析(通过模板页面逆向访问)代码示例
  3. Azure pipeline 配置根据条件执行脚本
  4. 复习Java_List_Set_HashSet原理_Collections使用_Comparator使用
  5. Numpy数据的操作 * dot() multiply() 的区别
  6. matlab米氏方程作图,根据米氏方程,符合[S]与Km 关系的是
  7. 5件你可能不知道可以使用 CSS-in-JS 来做的事情
  8. FutureTask的get()方法之异常处理
  9. SoilGrid 250米土壤质地数据集
  10. 通俗易懂讲PID,附参数调试口诀
  11. Linux内核 之 GDT LDT与分段
  12. Angularjs之模块(angular.module('myApp', [])参数)
  13. 【附源码】计算机毕业设计java兴发农家乐服务管理系统设计与实现
  14. Calander 类的使用
  15. ubuntu 桌面环境出现异常常用的解决方法
  16. 今年生男孩取什么名好的超简单起名方法
  17. 店铺信息html,编辑店铺信息.html
  18. 组装电脑配置推荐2022
  19. Maven笔记 - 第五章
  20. python 彩票分析_285期庄德福彩3D预测奖号:类型判断

热门文章

  1. 五、JAVA调用海康威视SDK实现摄像头内网转外网并前端展示
  2. 后端拼在字符串中的换行符\n如何在前端显示
  3. python实现grabcut算法进行物体分割
  4. Windows下使用PDH获取性能计数器(CPU、内存、网络流量等)
  5. python通过xpinyin和pypinyin进行汉字转拼音
  6. 人们通常先在线性表尾部临时添加一个_视频号——企业争夺的下一个爆款红利...
  7. Burp Suite-第八章 如何使用Burp Intruder
  8. 《可穿戴创意设计:技术与时尚的融合》一一1.1 概述
  9. 计算机科学与技术审核评估专家,教育部本科教学审核评估专家喻祖国莅临我院开展深度访谈...
  10. oracle数据库分区表建立索引