文章目录
一、MySQL 前言
菜鸟教程:https://www.runoob.com/mysql/mysql-tutorial.html
MySQL 是一种广泛使用的关系型数据库管理系统(RDBMS)。
它具有以下几个显著特点和优势:
- 开源免费:这使得它在成本方面具有很大的吸引力,尤其是对于小型和中型项目。
- 性能出色:能够处理大量的数据和高并发的请求。
- 易于使用:拥有相对简单的语法和操作方式,方便开发者上手。
在实际的使用中,MySQL 被广泛应用于各种类型的网站、应用程序和企业系统。例如,许多电商平台使用 MySQL 来存储商品信息、用户数据和订单数据;社交网络可能依靠它来管理用户的个人资料、好友关系和动态信息。
数据库术语:
名称 | 简称 | 含义 |
---|---|---|
数据库 | DataBase(DB) | 存储数据的仓库 |
数据库管理系统 | DataBase Management System(DBMS) | 操作和管理数据库的大型软件 |
SQL | Structured Query Language(SQL) | 操作关系型数据库的编程语言 |
数据库排行榜:
二、安装 MySQL
2.1 下载
下载地址:https://dev.mysql.com/downloads/installer/
2.2 安装
2.3 启动
在 Windows 自带的搜索框中输入:MySQL ,打开 MySQL 的客户端,输入上面安装教程中设置的密码,回车即可。
出现这些信息代表,MySQL 安装成功。
三、SQL 详解
SQL(Structured Query Language),即结构化查询语言,是用于管理关系数据库(如 MySQL)的标准语言。主要包括以下几类操作:
分类 | 全称 | 含义 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,定义数据库对象(数据库、表、字段) |
DML | Data Manipulation Language | 数据操作语言,用来对数据库的数据进行增、删、改操作 |
DQL | Data Query Language | 数据查询语言,用来查询数据库数据的操作 |
DCL | Data Control Language | 数据控制语言,用来控制数据库的访问权限和用户权限 |
3.1 约束
约束是用来约束表中字段的规则,作用是确保数据库中数据的完整性和一致性。
约束 | 含义 | 关键字 |
---|---|---|
非空约束 | 字段的值不能为null | not null |
唯一约束 | 字段的值是唯一,且不重复的 | unique |
主键约束 | 字段的值非空,且唯一 | primary key |
默认约束 | 如果字段没有值,则采用默认值 | default '默认值' |
外键约束 | 让两张表建立连接 | foreign key |
3.2 数据类型
MySQL 的数据类型有很多,主要分为三类:数值类型、字符串类型、日期时间类型。
菜鸟教程:https://www.runoob.com/mysql/mysql-data-types.html
3.3 条件
条件用于查询、修改和删除操作,作用是筛选出符合特定条件的数据。
比较运算符
运算符 | 含义 |
---|---|
= | 等于 |
!= 或 <> | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
逻辑运算符
运算符 | 含义 |
---|---|
and 或 && | 并且,多个条件同时满足 |
or 或 || | 或者,多个条件满足其一 |
not 或 ! | 非,否定一个条件 |
范围条件
运算符 | 含义 |
---|---|
between … and … | 指定一个值的范围,包括边界值 |
in | 匹配一组值中的任何一个 |
模糊匹配
like:用于模式匹配。% 表示任意字符序列(包括空字符序列),_ 表示任意单个字符。
空值判断
运算符 | 含义 |
---|---|
is null | 判断是否为 null 值 |
is not null | 判断是否不为 null 值 |
这些条件可以根据具体的需求组合使用,实现复杂的数据筛选。
3.4 DDL
操作数据库
-- 查询所有数据库
SHOW DATABASES;
-- 查询当前的数据库
SELECT DATABASE();
-- 创建数据库,中括号中的内容是可选的
CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则];
-- 删除数据库,中括号中的内容是可选的
DROP DATABASE [IF EXISTS] 数据库名;
-- 使用数据库
USE 数据库名;
操作表
-- 创建表,注意表的最后一个字段是没有逗号的,中括号中的内容是可选的
CREATE TABLE 表名 (
字段1 字段类型 [约束] [comment 字段1注释],
......
字段n 字段类型 [约束] [comment 字段n注释]
) [comment '表注释'];
-- 查询当前数据库的所有表
SHOW TABLES;
-- 查询表的结构
DESC 表名;
-- 查询表的建表语句
SHOW CREATE TABLE 表名;
-- 新增一个字段,中括号中的内容是可选的
ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
-- 修改字段的数据类型
ALTER TABLE 表名 MODIFY 字段名 新的数据类型(长度);
-- 修改字段的字段名和数据类型,中括号中的内容是可选的
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 数据类型(长度) [COMMENT 注释] [约束];
-- 修改表的名称
ALTER TABLE 表名 RENAME TO 新表名;
-- 删除表,中括号中的内容是可选的
DROP TABLE [IF EXISTS] 表名;
-- 删除表,并重新创建该表,表中的数据清理,表结构依然存在
TRUNCATE TABLE 表名;
-- 删除表的字段
ALTER TABLE 表名 DROP 字段名;
3.5 DML
-- 添加数据
INSERT INTO 表名 (字段1, 字段2, ..., 字段n) values (值1, 值2, ..., 值n);
-- 修改数据,中括号中的内容是可选的,如果不加则修改的是整张表的数据
UPDATE 表名 SET 字段1 = 值1, 字段2 = 值2, ..., 字段n = 值n [WHERE 条件];
-- 删除数据,中括号中的内容是可选的,如果不加则删除的是整张表的数据
DELETE FROM 表名 [WHERE 条件];
3.6 DQL
基本查询
-- 查询多个字段
SELECT 字段1, 字段2, ..., 字段n FROM 表名;
-- 查询所有字段
SELECT * FROM 表名;
-- 设置别名
SELECT 字段1 [AS 别名1], 字段2 [AS 别名2], ..., 字段n [AS 别名n] FROM 表名;
-- 去重表中重复的记录
SELECT DISTINCT 字段列表 FROM 表名;
条件查询
SELECT * FROM 表名 WHERE 条件列表;
聚合查询
聚合函数是将一列的数据作为一个整体然后进行计算的函数。
函数 | 含义 |
---|---|
count | 统计数量,不包含 null 值 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
SELECT 聚合函数(字段列表) FROM 表名;
分组查询
-- 中括号的内容是可选的
SELECT 字段列表 FROM 表名 [WHERE 条件] group by 分组的字段 [HAVING 分组后的过滤条件];
排序查询
-- 中括号的内容是可选的
SELECT 字段列表 FROM 表名 [WHERE 条件] [group by 分组字段] order by 字段列表 排序方式;
排序方式:
- asc(默认):升序,从小到大;
- desc:降序,从大到小。
分页查询
-- 起始索引从0开始
SELECT 字段列表 FROM 表名 limit 起始索引,查询多少个;
-- 样例
select * from user limit 0,5;
select * from user limit 5,10;
3.7 DCL
管理用户
-- 查询用户
USE mysql;
SELECT * FROM user;
-- 创建用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '用户密码';
-- 修改用户密码
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password by '新密码';
-- 删除用户
DROP USER '用户名'@'主机名';
注意:
- 主机名可以使用 % 通配(任意主机都可以),也可以使用 localhost(本机),表示的是哪台计算机可以访问当前数据库;
- 这类的 SQL ,我们开发人员操作的比较少。
管理权限
MySQL 中定义了很多权限,常用的有以下几种:
权限 | 含义 |
---|---|
ALL | 所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
-- 查询用户的权限
SHOW GRANTS FOR '用户名'@'主机号';
-- 授予用户权限
GRANT 权限列表 ON 数据库.表 TO '用户名'@'主机号';
-- 撤销用户权限
REVOKE 权限列表 ON 数据库.表 FROM '用户名'@'主机名';
注意:
- 多个权限之间可以用逗号隔开;
- 数据库和表名可以使用 * 进行通配,表示所有。
四、多表设计
在 MySQL 中,进行多表设计是构建高效、可靠数据库的关键步骤。以下是一些多表设计的要点和示例:
-
明确业务需求
: 首先要了解业务流程和数据之间的关系。比如,在一个电商系统中,可能有用户表、订单表、商品表等。 -
确定表的结构
:为每个表定义合适的列,包括主键、外键等。 -
选择合适的表关系
:- 一对多:一个表的一行可以与另一个表的多行相关联。一个部门可以有多个员工,多个员工只能归属一个部门。
- 一对一:一个表的一行可以与另一个表的多行相关联,与一对多不同的是,关联的字段是唯一的。用户与身份证的关系。
- 多对多:两个表中的多行可以相互关联。学生和课程就是多对多的关系,一个学生可以选多门课程,一门课程也可以供多门学生选择。这种情况通常需要一个中间表来建立关系。
-
规范化设计
:遵循数据库规范化原则,减少数据冗余和数据不一致性。通常至少达到第三范式。 -
考虑性能优化
:适当建立索引,提高查询效率。但过多的索引可能会影响数据插入和更新的性能。 -
数据一致性和完整性
:通过约束(如主键约束、外键约束、非空约束等)确保数据的一致性和完整性。
总之,多表设计需要综合考虑业务需求、数据关系、性能和数据质量等多个方面,以构建一个合理、高效的数据库结构。您是正在进行一个新的数据库项目的多表设计吗?
4.1 一对多
在 MySQL 中,一对多关系是常见的表关系类型,而实现这种关系时,可以使用逻辑外键和物理外键。
逻辑外键
不在数据库表结构中定义实际的外键约束,而是通过在应用程序的代码逻辑中进行控制和验证,通过在数据库表 "多"
的一方,添加字段,来关联 "一"
的一方的主键
-- 部门表(一)
create table tb_dept (
id int primary key auto_increment comment 'ID',
name varchar(50) comment '部门名'
) comment '部门表';
-- 员工表(多)
create table tb_emp (
id int primary key auto_increment comment 'ID',
name varchar(50) comment '姓名',
age tinyint unsigned comment '年龄',
dept_id int comment '部门ID'
) comment '员工表';
物理外键
目前上述的两张表,在数据库层面并未建立关联,所以无法保证数据的一致性和完整性。如果想要保证数据的一致性和完整性,需要在数据库表结构中实际定义的外键约束,通过在 "多"
的一方的表中创建一个字段,该字段引用 "一"
的一方表的主键。
-- 创建表时指定
create table 表名(
字段名 数据类型,
...
[constraint] [外键名] foreign key (外键字段名) references 主表(字段名)
);
-- 创建完表后,添加外键
alter table 表名 add constraint 外键名 foreign key (外键字段名) references 主表(字段名);
-- 部门表(一)
create table if not exists tb_dept (
id int primary key auto_increment comment '部门ID',
name varchar(50) comment '部门名'
) comment '部门表';
insert into tb_dept (name) values ('人事部');
insert into tb_dept (name) values ('财政部');
-- 员工表(多)
create table tb_emp (
id int primary key auto_increment comment 'ID',
name varchar(50) comment '姓名',
age tinyint unsigned comment '年龄',
dept_id int comment '部门ID',
constraint fk_emp_dept foreign key (dept_id) references tb_dept(id)
) comment '员工表';
insert into tb_emp(name, age, dept_id) values ('张三', 18, 1);
insert into tb_emp(name, age, dept_id) values ('李四', 18, 2);
insert into tb_emp(name, age, dept_id) values ('王五', 18, 1);
-- 添加外键
-- alter table tb_emp add constraint 外键名 foreign key (dept_id) references tb_dept(id);
4.2 一对一
一对一的关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他字段放在另一张表中,以提高效率。通过在任意一方加入外键来关联另外一张表的主键,并且设置外键为唯一(UNIQUE)。
-- 用户表
create table tb_user (
id int primary key auto_increment comment '用户ID',
name varchar(50) comment '姓名',
age tinyint unsigned comment '年龄'
) comment '用户表';
insert into tb_user (name, age) values ('张三', 18);
insert into tb_user (name, age) values ('李四', 20);
-- 用户信息表
create table tb_user_card (
id int primary key auto_increment comment 'ID',
birthday date not null comment '生日',
id_card varchar(18) not null comment '身份证号',
user_id int not null unique comment '用户ID',
constraint fk_user_id foreign key (user_id) references tb_user(id)
) comment '用户信息表';
insert into tb_user_card (birthday, id_card, user_id) values ('2000-06-10', '100001021000000100', 1);
insert into tb_user_card (birthday, id_card, user_id) values ('2003-08-03', '100001021000000101', 2);
4.3 多对多
通过创建一个中间表,中间表中至少包含两个外键,分别用来关联两方的主键。
-- 学生表
create table tb_student (
id int auto_increment primary key comment '学生ID',
name varchar(10) comment '姓名',
no varchar(10) comment '学号'
) comment '学生表';
insert into tb_student (name, no) values ('张三', 20030803);
insert into tb_student (name, no) values ('李四', 20010901);
-- 课程表
create table tb_course(
id int auto_increment primary key comment '课程ID',
name varchar(10) comment '课程名'
) comment '课程表';
insert into tb_course (name) values ('语文');
insert into tb_course (name) values ('数学');
insert into tb_course (name) values ('英文');
-- 中间表
create table tb_student_course (
id int auto_increment primary key comment 'ID',
student_id int not null comment '学生ID',
course_id int not null comment '课程ID',
constraint fk_student_id foreign key (student_id) references tb_student(id),
constraint fk_course_id foreign key (course_id) references tb_course(id)
) comment '学生课程中间表';
insert into tb_student_course (student_id, course_id) values (1,1);
insert into tb_student_course (student_id, course_id) values (1,2);
insert into tb_student_course (student_id, course_id) values (1,3);
insert into tb_student_course (student_id, course_id) values (2,1);
insert into tb_student_course (student_id, course_id) values (2,3);
五、多表查询
通常情况下,一个数据库中会存在多个表,这些表之间通过某些共同的字段(主键和外键)建立了关联关系,而多表查询是指在数据库中从两个或更多个相关联的表中获取所需数据的操作。
5.1 数据
-- 部门表
create table tb_dept (
id int auto_increment primary key comment '部门ID',
name varchar(20) comment '部门名'
) comment '部门表';
insert into tb_dept (name) values ('人事部'), ('财政部'), ('就业部');
-- 员工表
create table tb_emp (
id int auto_increment primary key comment '员工ID',
name varchar(50) comment '姓名',
dept_id int comment '部门ID',
constraint fk_dept_id foreign key (dept_id) references tb_dept(id),
create_date date comment '入职时间'
) comment '员工表';
insert into tb_emp (name, dept_id, create_date ) values
('张三', 1, now()),
('李四', 2, now()),
('王五', 1, now()),
('赵六', null, '2003-08-03');
-- 多表查询
select * from tb_emp, tb_dept where tb_emp.dept_id = tb_dept.id;
运行结果:
5.2 内连接
查询左表和右表的交集数据。
语法
-- 隐式内连接
select 字段列表 from 表1, 表2 where 条件 ...;
-- 显示内连接,中括号的内容可以不写
select 字段列表 from 表1 [inner] join 表2 on 连接条件 ...;
测试
-- A. 查询员工的姓名以及所属的部门 (隐式内连接)
select tb_emp.name, tb_dept.name
from tb_emp, tb_dept
where tb_emp.dept_id = tb_dept.id;
-- B. 查询员工的姓名以及所属的部门 (显示内连接)
select tb_emp.name, tb_dept.name
from tb_emp inner join tb_dept
on tb_emp.dept_id = tb_dept.id
运行结果:
5.3 外连接
外连接分为左外连接和有外连接,语法如下:
-- 左外连接,中括号的内容可以不写
select 字段列表 from 表1 left [outer] join 表2 连接条件 ...;
-- 右外连接,中括号的内容可以不写
select 字段列表 from 表1 right [outer] join 表2 连接条件 ...;
左外连接
查询左表,以及左表和右表交集部分
-- A. 查询所有员工的姓名以及所属部门
select tb_emp.name, tb_dept.name
from tb_emp left outer join tb_dept
on tb_emp.dept_id = tb_dept.id;
运行结果:
右外连接
查询右表,以及右表和左表交集部分。需要注意的是右外连接可以被左外连接代替,只要调换一下表的位置就可以,所以一般我们会使用左外连接。
-- A. 查询部门表所有的部门名称以及归属的员工
select tb_dept.name, tb_emp.name
from tb_emp right outer join tb_dept
on tb_dept.id = tb_emp.dept_id;
运行结果:
5.4 子查询
子查询是一个嵌套在另一个查询(主查询)中的查询。子查询可以用于实现复杂的查询逻辑和数据筛选。子查询的外部可以是 insert / update / delete / select 的任何一个,最常见的是 select 。
标量子查询
子查询的结果会返回单个值。
-- A. 查询人事部的所有员工信息
-- 第一步. 查询人事部的部门ID
-- select id from tb_dept where name = '人事部';
-- 第二步. 根据查询出来的ID,在员工表的部门ID中查找,如果相等,代表该员工归属该部门
select * from tb_emp
where tb_emp.dept_id = (select id from tb_dept where name = '人事部');
运行结果:
列子查询
子查询会返回一列值。
-- A. 查询人事部和财政部的所有员工信息
-- 1. 查询人事部和财政部的部门ID
-- select id from tb_dept where name = '人事部' or name = '财政部';
-- 2. 根据查询出来的ID列数据,在员工表的部门ID中查找,如果相等,代表该员工归属该部门
select * from tb_emp
where tb_emp.dept_id in (select id from tb_dept where name = '人事部' or name = '财政部');
运行结果:
行子查询
子查询的结果会返回一行数据。
-- A. 查询与张三入职日期以及部门都相同的员工信息;
-- 第一步. 查询张三的入职日期和部门
-- select create_date, dept_id from tb_emp where name = '张三';
-- 第二步. 根据查询出来的行数据,在员工表中查询对应的数据,如果相等,则匹配到入职日期以及部门都相同的员工
select * from tb_emp
where (create_date, dept_id) = (select create_date, dept_id from tb_emp where name = '张三');
运行结果:
表子查询
子查询的结果会返回一个多行多列的数据,可以作为一个临时表在主查询中使用。
-- A. 查询入职时间在 2003-08-03 之后的员工信息以及部门名称
-- 第一步. 查询入职时间在 2003-08-03 之后的员工
-- select * from tb_emp where create_date > '2003-08-03';
-- 第二步. 根据这些信息,查询到部门信息
select e.*, d.name
from (select * from tb_emp where create_date > '2003-08-03') as `e`, tb_dept as `d`
where e.dept_id = d.id;
运行结果:
六、MySQL 事务
MySQL 事务是一组数据库操作的集合,这些操作要么全部成功执行,要么全部不执行,以保证数据的一致性和完整性。
6.1 ACID
事务具有以下四个重要特性,通常称为 ACID 特性:
原子性(Atomicity)
原子性指的是事务中的所有操作要么全部成功执行,要么全部不执行,就如同一个不可分割的原子。
例如,假设我们有一个包含两个操作的事务:从账户 A 转出 100 元,并将这 100 元存入账户 B。
如果在执行过程中,从账户 A 成功转出了 100 元,但在存入账户 B 时由于某种原因(如网络故障、数据库错误等)失败了,那么整个事务必须回滚,就好像这两个操作都没有发生过一样,即账户 A 的钱不会减少,账户 B 的钱也不会增加。
一致性(Consistency)
一致性指的是事务执行的结果必须使数据库从一个一致性状态转换到另一个一致性状态,强调的是数据的完整性和准确性,无论事务执行成功还是失败,数据库中的数据都必须保持一致。
例如,假设有一个银行系统,存在账户余额不能为负数的约束。如果一个事务包含从账户中取款的操作,而取款后导致余额变为负数,那么这个事务就违反了一致性原则,应该被回滚或采取相应的纠错措施,以确保账户余额始终符合约束条件。
隔离性(Isolation)
隔离性是指多个事务并发执行时,它们之间相互隔离,互不干扰。每个事务都感觉不到其他事务在并发地执行,就好像在独立地操作数据库,主要目的是防止并发事务之间的相互影响,避免出现数据不一致、脏读、不可重复读和幻读等问题。
以下是几种常见的隔离级别:
- 读未提交(Read Uncommitted):一个事务可以读取另一个未提交事务的数据。这可能导致脏读问题,即读取到了未提交的数据,如果回滚,这些数据可能是无效的。
例如,事务 A 修改了一条数据但未提交,事务 B 此时读取到了该数据,然后事务 A 回滚,那么事务 B 读取到的就是脏数据。 - 读已提交(Read Committed):一个事务只能读取已经提交的数据,避免了脏读,但可能导致不可重复读问题。不可重复读是指在同一个事务中,多次读取同一数据得到的结果不同。
例如,事务 A 读取了某条数据,事务 B 对其进行了修改并提交,然后事务 A 再次读取该数据时结果不同。 - 可重复读(Repeatable Read):这是 MySQL 的默认隔离级别。在一个事务中多次读取相同的数据,结果是一致的,避免了不可重复读,但可能出现幻读问题。幻读是指当一个事务基于某个条件读取数据时,另一个事务插入了满足该条件的新数据,导致第一个事务再次执行相同查询时,结果集发生了变化。
例如,事务 A 基于某个条件查询得到结果集,事务 B 插入了满足条件的新数据并提交,事务 A 再次执行相同查询时结果集多了新数据。 - 串行化(Serializable):这是最高的隔离级别,通过强制事务串行执行,避免了上述所有问题,但可能会影响并发性能。
隔离级别的选择取决于具体的应用场景和对数据一致性、并发性能的要求。在实际应用中,需要根据业务需求权衡隔离性和性能之间的关系。
持久性(Durability)
持久性指的是一旦事务被成功提交,它对数据库所做的更改就会被永久保存,即使系统出现故障(如断电、服务器崩溃等),数据也不会丢失。
例如,在一个在线教育平台的数据库中,学生成功报名了一门课程,这个报名操作被包含在一个事务中并且成功提交。即使之后数据库服务器突然发生故障,当系统恢复时,学生报名课程的记录仍然存在,不会因为故障而丢失。
6.2 操作事务
MySQL 默认事务是自动提交的,也就是说当执行一条 增、删、改
操作时,MySQL 都会立即隐式的提交事务。
所以我们就需要将一系列操作都控制在一个事务中,让这些操作要么同时成功,要么同时失败,这样就可以保证数据的一致性和完整性。
可以通过以下语句来开启、提交和回滚事务:
-- 开启事务
START TRANSACTION;
-- 执行一系列操作
......
-- 操作全部执行成功,则提交事务
COMMIT;
-- 如果有一个操作失败,则回滚事务
ROLLBACK;
事务在许多场景中非常有用,比如银行转账、订单处理、库存管理等,确保数据的准确性和可靠性。
例如,在电商网站的订单处理中,如果同时涉及到库存更新、用户账户扣款和订单记录创建等操作,就需要将这些操作放在一个事务中,以防止部分操作成功而部分操作失败导致的数据不一致问题。
七、MySQL 索引
在 MySQL 中,索引是一种用于加快数据检索的数据结构。它类似于书籍的目录,可以帮助数据库快速定位和获取所需的数据,从而提高查询的效率。
7.1 特点
优点
- 显著提高查询速度:能够快速定位到符合条件的数据,减少数据的扫描量。
- 加速排序和分组操作:如果索引列被用于排序或分组,数据库可以更高效地完成这些操作。
缺点
- 增加数据增、删和改的效率:因为每次对数据进行修改时,都需要同时维护索引。
- 占用额外的存储空间:存储索引数据需要额外的磁盘空间。
7.2 索引结构
MySQL 支持的索引结构有很多,如:Hash 索引、B+Tree 索引、Full-Test 索引等,如果没有特别说明,都是指默认的 B+Tree 结构的索引。
哈希索引
哈希索引基于哈希表实现。通过对索引列的值进行哈希计算,得到一个哈希值,然后根据哈希值快速定位数据。哈希索引适用于精确匹配查询,即查询条件中索引列的值能精确匹配。但它不支持范围查询、排序和联合索引。
B+树索引
B+树是一种平衡的多路查找树。它的特点是所有的数据都存储在叶子节点,非叶子节点只存储索引信息,这使得 B+树在进行范围查询和排序操作时非常高效。在 InnoDB 存储引擎中,主键索引通常采用 B+树结构。
全文索引
全文索引主要用于对文本字段进行搜索。它可以快速查找包含特定关键词的文本。
7.3 操作索引
在 MySQL 中创建索引的语法如下:
-- 创建索引,中括号的内容可以省略
create [unique] index 索引名 on 表名(字段名1, ...);
-- 样例
create index tb_user_name on tb_user(name);
-- 查看表的索引
show index from 表名;
-- 样例
show index from tb_user;
-- 删除索引
drop index 索引名 on 表名;
-- 样例
drop index tb_user_name on tb_user;
注意点:
-
当你创建表时,为表中某一个字段设置为主键字段,会自动创建一个主键索引,主键索引的查询效率是最高的;
-
当你为表中某一个字段添加一个唯一约束(UNIQUE)时,数据库会去添加唯一索引。
-
选择经常用于查询、连接、排序和分组操作的列上创建索引。比如在订单表中,订单号、客户 ID 等经常用于查询的列适合创建索引。避免在数据量小的表上创建过多索引,因为可能不会带来明显的性能提升,反而增加维护成本。对于经常更新的列,要谨慎创建索引,以免影响数据更新的效率。
例如,在一个电商网站的用户表中,如果经常根据用户名来查找用户信息,那么为用户名列创建索引是合理的。但如果很少根据用户的地址进行查询,为地址列创建索引可能就不太必要。
总之,合理地创建和使用索引可以极大地优化数据库的性能,但不当的索引创建可能会带来负面效果。