目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

索引

索引


索引是一个单独的,存储在磁盘中上的数据库结构,它们包含着对数据表里的所有记录的引用指针。使用索引可以快速的找出在某列或多列中有特定值的行。

索引的优点


通过创建唯一索引,来保证数据库表中的每一行数据的唯一性。

  • 可以加快数据的检索速度。
  • 可以保证表数据的完整性与准确性

索引的缺点


索引需要占用物理空间。

  • 对表中的数据进行改动时,索引也需要跟着动态维护,降低了数据的维护速度。

索引的常见类型

  • index:普通索引
  • unique:唯一索引
  • primary key:主键索引
  • foreign key:外键索引
  • fulltext: 全文索引
  • 组合索引

准备数据

 1# 准备shell脚本
 2[root@localhost ~]# vim /test/test.sh
 3
 4#!/bin/bash
 5echo "请输入字段servnumber的值:"
 6read serber
 7echo "请输入创建sql语句的数量:"
 8read number
 9
10# char=`head /dev/urandom | tr -dc 0-9 | head -c 11`
11for (( i=0;i<$number;i++ ))
12        do
13        pass=`head /dev/urandom | tr -dc a-z | head -c 8`
14        let serber=serber+1
15        echo "insert into test(id,username,servnumber,password,createtime) values('$i','user${i}','${serber}','$pass',now());" >>sql.txt
16    done
17
18# 生成sql脚本
19[root@localhost test]# sh test.sh 
20请输入字段servnumber的值:
2114223332345
22请输入创建sql语句的数量:
231000
24[root@localhost test]# ls
25sql.txt  test.sh
26
27
28# sql脚本从本机复制到容器中
29docker cp 本地路径 容器长ID:容器路径
30[root@localhost test]# docker cp /test/sql.txt  mysql:/sql.txt
31
32# 创建test
33create table test (
34    id int(7) zerofill auto_increment not null,
35    username varchar(20),
36    servnumber varchar(30),
37    password varchar(20),
38    createtime datetime,
39    primary key (id)
40)DEFAULT CHARSET=utf8;
41
42# 插入数据
43mysql> source /sql.txt
44Query OK, 1 row affected (0.02 sec)
45Query OK, 1 row affected (0.01 sec)
46
47# 查看生成的数据
48mysql> select * from test limit 10;
49+---------+----------+-------------+----------+---------------------+
50| id      | username | servnumber  | password | createtime          |
51+---------+----------+-------------+----------+---------------------+
52| 0000001 | user0    | 15223334346 | gsfzlosh | 2019-07-20 08:58:34 |
53| 0000002 | user2    | 15223334348 | iooedzbw | 2019-07-20 08:58:34 |
54| 0000003 | user3    | 15223334349 | stygrpgj | 2019-07-20 08:58:34 |
55| 0000004 | user4    | 15223334350 | hodkesca | 2019-07-20 08:58:34 |
56| 0000005 | user5    | 15223334351 | beyitktf | 2019-07-20 08:58:34 |
57| 0000006 | user6    | 15223334352 | xgwqdden | 2019-07-20 08:58:34 |
58| 0000007 | user7    | 15223334353 | pbhhvcus | 2019-07-20 08:58:34 |
59| 0000008 | user8    | 15223334354 | sevxjxkn | 2019-07-20 08:58:34 |
60| 0000009 | user9    | 15223334355 | hntiujvu | 2019-07-20 08:58:34 |
61| 0000010 | user10   | 15223334356 | kcvqcvgi | 2019-07-20 08:58:34 |
62+---------+----------+-------------+----------+---------------------+

普通索引

 普通索引(index)顾名思义就是各类索引中最为普通的索引,主要任务就是提高查询速度。其特点是允许出现相同的索引内容,允许空(null)值。

  • 当创建索引没有指定索引名时,索引吗默认为字段的名称。
 1# 创建表时添加普通索引
 2create table test (
 3    id int(7) zerofill auto_increment not null,
 4    username varchar(20),
 5    servnumber varchar(30),
 6    password varchar(20),
 7    createtime datetime,
 8    index (id)
 9)DEFAULT CHARSET=utf8;
10
11# 添加普通索引(已经创建好的表)  普通索引允许索引字段中存在相同的值。
12mysql> alter table test add index index_createtime (createtime);
13Query OK, 0 rows affected (0.08 sec)
14Records: 0  Duplicates: 0  Warnings: 0
15
16# 直接创建普通索引 
17mysql> create index index_createtime on test (createtime);
18
19# 查看表中索引
20mysql> show index from test\G
21mysql> show create table test\G
22
23# 删除索引
24mysql> drop index index_createtime on test;
25Query OK, 0 rows affected (0.06 sec)
26Records: 0  Duplicates: 0  Warnings: 0

测试查询时间(100W 条数据)
 随着表结构的复杂度增加和数据量的增加,索引查询带来的性能优势会越来越明显,这里测试的表结构相对简单,数据量也只有 100W 条。

1# 不使用索引字段作为查询条件:查询耗时0.28
2mysql> select * from test where password='hiavzobu';
31 row in set (0.28 sec)
4
5# 添加索引,再次查询:查询耗时0.00
6mysql> alter table test add index index_password (password);
7mysql> select * from test where password='hiavzobu';
81 row in set (0.00 sec)

唯一索引

 (unique)顾名思义就是不可以出现相同的索引内容,但是可以为空(null)值。

 1# 创建表时添加唯一索引
 2create table test (
 3
 4    id int(7) zerofill auto_increment not null,
 5    username varchar(20),
 6    servnumber varchar(30),
 7    password varchar(20),
 8    createtime datetime,
 9    index (id)
10)DEFAULT CHARSET=utf8;
11
12# 添加唯一索引(已经创建好的表)
13mysql>  alter table test add unique unique_username (username);
14Query OK, 0 rows affected (0.13 sec)
15Records: 0  Duplicates: 0  Warnings: 0
16
17# 查看表中索引
18mysql> show index from test\G
19mysql> show create table test\G
20
21# 删除索引
22mysql> drop index unique_username on test;
23Query OK, 0 rows affected (0.05 sec)
24Records: 0  Duplicates: 0  Warnings: 0

主键索引

 基于主键添加索引就是主键索引,它是一种特殊的唯一索引,不允许有空值,而唯一索引(unique 是允许为空值的)。指定为“PRIMARY KEY”。

  • 主键:主键是表的某一列,这一列的值可以用来标志表中的每一行数据的。
 1################### 创建主键
 2# 创建主键方式一: 创建表的时候创建
 3
 4# 创建主键方式二:直接为表添加主键索引
 5mysql> alter table test add primary key (id);
 6Query OK, 0 rows affected (0.47 sec)
 7Records: 0  Duplicates: 0  Warnings: 0
 8
 9################### 删除主键
10# 注意:在有自增的情况下,必须先删除自增,才可以删除主键
11mysql> desc test;
12+------------+--------------------------+------+-----+---------+----------------+
13| Field      | Type                     | Null | Key | Default | Extra          |
14+------------+--------------------------+------+-----+---------+----------------+
15| id         | int(7) unsigned zerofill | NO   | PRI | NULL    | auto_increment |
16| username   | varchar(20)              | YES  |     | NULL    |                |
17| servnumber | varchar(30)              | YES  |     | NULL    |                |
18| password   | varchar(20)              | YES  | MUL | NULL    |                |
19| createtime | datetime                 | YES  |     | NULL    |                |
20+------------+--------------------------+------+-----+---------+----------------+
215 rows in set (0.00 sec)
22
23mysql> alter table test change id id int(7) unsigned zerofill not null;
24Query OK, 999 rows affected (0.28 sec)
25Records: 999  Duplicates: 0  Warnings: 0
26
27mysql> desc test;
28+------------+--------------------------+------+-----+---------+-------+
29| Field      | Type                     | Null | Key | Default | Extra |
30+------------+--------------------------+------+-----+---------+-------+
31| id         | int(7) unsigned zerofill | NO   | PRI | NULL    |       |
32| username   | varchar(20)              | YES  |     | NULL    |       |
33| servnumber | varchar(30)              | YES  |     | NULL    |       |
34| password   | varchar(20)              | YES  | MUL | NULL    |       |
35| createtime | datetime                 | YES  |     | NULL    |       |
36+------------+--------------------------+------+-----+---------+-------+
375 rows in set (0.00 sec)
38
39# 删除主键
40mysql> alter table test drop primary key;

测试查询时间(100W 条数据)

1# 没有主键索引情况下查询,耗时:0.41
2mysql> alter table test drop primary key;
3mysql> select * from test where id='0999999';
41 rows in set (0.41 sec)
5
6# 添加主键索引再次查询,耗时:0.00
7mysql> alter table test add primary key (id);
8mysql> select * from test where id='0999999';
91 rows in set (0.00 sec)

全文索引

 全文索引是将存储在数据库中的文章或者句子等任意内容信息查找出来的索引,单位是词。全文索引也是目前搜索引擎使用的一种关键技术。指定为 fulltex。

  • mysql5.6 版本字后,innodb 引擎也支持全文检索功能。
  • 出现频率很高的词,将会使全文索引失效。全文索引不针对非常频繁的词做索引。比如 is,no,not,you,me,yes 这些,称之为停止词。
  • 对英文检索时忽略大小写。
  • 一般情况下创建全文索引的字段数据类型为 char、varchar、text 。其它字段类型不可以。
  • 使用通配符*时,只能放在词的后边,不能放前边。
  • 出现频率很高的词,将会使全文索引失效 in boolean mode:意思是指定全文检索模式为布尔全文检索(简单可以理解为是检索方式);select * from 表名 where match (字段名) against ('检索内容' in boolean mode);

外键约束

 外键就是作用于两个表数据之间的链接的一列或多列,用来保证表与表之间的数据的完整性和准确性。例如:员工表和部门表,外键可以保证每一个员工都能有自己所属的部门,保证了不会出一个员工没有部门的情况出现。

  • 两张表,主键跟外键的字段类型一定要相同。
  • 要使用外键约束表的引擎一定得是 InnoDB 引擎,MyISAM 是不起作用的。
  • 在干掉外键索引之前必须先把外键约束删除,才能删除索引。
 1################### 添加外键约束
 2#  方式一:创建表时候声明外键约束
 3CREATE TABLE `employee` (
 4  `empno` int(11) NOT NULL COMMENT '雇员编号',
 5  `ename` varchar(50) DEFAULT NULL COMMENT '雇员姓名',
 6  `job` varchar(30) DEFAULT NULL,
 7  `mgr` int(11) DEFAULT NULL COMMENT '雇员上级编号',
 8  `hiredate` date DEFAULT NULL COMMENT '雇佣日期',
 9  `sal` decimal(7,2) DEFAULT NULL COMMENT '薪资',
10  `deptnu` int(11) DEFAULT NULL COMMENT '部门编号',
11  PRIMARY KEY (`empno`),
12 foreign key (deptnu) references dept(deptnu)
13) ENGINE=InnoDB DEFAULT CHARSET=utf8;
14
15# 方式二:基于已创建的表添加外键
16mysql> alter table employee add foreign key (deptnu) references dept(deptnu)
17
18
19
20# 查看表
21mysql> show create table employee\G
22
23*************************** 1. row ***************************
24       Table: employee
25Create Table: CREATE TABLE `employee` (
26  `empno` int(11) NOT NULL,
27  `ename` varchar(50) DEFAULT NULL,
28  `job` varchar(30) DEFAULT NULL,
29  `mgr` int(11) DEFAULT NULL,
30  `hiredate` date DEFAULT NULL,
31  `sal` decimal(7,2) DEFAULT NULL,
32  `deptnu` int(11) DEFAULT NULL,
33  PRIMARY KEY (`empno`),
34  KEY `deptnu` (`deptnu`),
35  CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`deptnu`) REFERENCES `dept` (`deptnu`)
36) ENGINE=InnoDB DEFAULT CHARSET=utf8
371 row in set (0.00 sec)
38
39# 删除外键约束
40mysql> alter table employee drop foreign key employee_ibfk_1;
41
42# 再次查看表
43mysql> show create table employee\G
44*************************** 1. row ***************************
45       Table: employee
46Create Table: CREATE TABLE `employee` (
47  `empno` int(11) NOT NULL,
48  `ename` varchar(50) DEFAULT NULL,
49  `job` varchar(30) DEFAULT NULL,
50  `mgr` int(11) DEFAULT NULL,
51  `hiredate` date DEFAULT NULL,
52  `sal` decimal(7,2) DEFAULT NULL,
53  `deptnu` int(11) DEFAULT NULL,
54  PRIMARY KEY (`empno`),
55  KEY `deptnu` (`deptnu`)
56) ENGINE=InnoDB DEFAULT CHARSET=utf8
57
58#注意:在干掉外键索引之前必须先把外键约束删除,才能删除索引
59mysql> alter table employee drop index deptnu;
60ERROR 1553 (HY000): Cannot drop index 'deptnu': needed in a foreign key constraint
61mysql> alter table employee drop foreign key employee_ibfk_1;
62mysql> alter table employee drop index deptnu;

联合索引

 联合索引又称组合索引或者复合索引,是建立在俩列或者多列以上的索引。

  • 为什么要使用联合索引,而不使用多个单列索引?:联合索引的效率远远高于单列索引。
  • 联合索引的最左原则:组合索引需要有最左边的第一个字段,才能让整个联合索引生效。

索引的使用原则

  • 索引并非越多越好,过多的索引会增加数据的维护速度还有磁盘空间的浪费。
  • 当表的数据量很大的时候,可以考虑建立索引。
  • 表中经常查数据的字段,可以考虑建立索引。
  • 想要保证表中数据的唯一性,可以考虑建立唯一索引。
  • 想要保证俩张表中的数据的完整性跟准确性,可以考虑建立外键约束。
  • 经常对多列数据进行查询时,可以考虑建立联合索引。

作者:Soulboy