MySQL的高级用法和性能优化
- 1. MySQL的高级用法
- 1.1 replace into 用法
- 1.2 内连接(inner join)
- 1.2.1 等值连接
- 1.2.2 非等值连接
- 1.2.3 左连接
- 1.2.4 右连接
- 1.3 索引
- 1.3.1 索引的概念
- 1.3.2 索引的分类
- 1.3.3 索引的优点
- 1.3.4 索引的缺点
- 1.3.5 索引的使用场景
- 2. 性能优化
- 2.1 避免索引失效
- 2.2 SQL 语句调优
- 2.3 合理的数据库设计
- 2.4 定位执行效率慢的 sql 语句
欢迎阅读本文,今天我们将一同深入学习数据库操作的高级用法以及性能优化的技巧。数据库作为现代应用的重要组成部分,其高效操作和性能优化对于应用的稳定性和用户体验至关重要。通过本文的学习,您将能够掌握一些常用的数据库性能优化技巧,从而提升应用的性能和响应速度。
1. MySQL的高级用法
1.1 replace into 用法
replace into
与 insert into
功能类似
replace into
首先尝试插入数据到列表中,
- 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。
- 否则,直接插入新数据。
要注意的是:插入数据的表必须有主键或者是唯一索引!否则的话,replace into
会直接插入数据,这将导致表中出现重复的数据。
replace into table_name(col_name, ...) values(...)
replace into table_name(col_name, ...) select ...
replace into table_name set col_name = value,...
1.2 内连接(inner join)
1.2.1 等值连接
-
概述
指使用等号"="比较两个表的连接列的值,相当于两表执行笛卡尔后,取两表连接列值相等的记录。
-
语法
SELECT 列 FROM 表1 INNER JOIN 表2 ON 表1.列 = 表2.列
1.2.2 非等值连接
-
概述
指使用大于号">“或小于号”<"比较两个表的连接列的值,相当于两表执行笛卡尔积后,取一个表大于或小于另一个表的连接列值的记录。
-
语法
SELECT 列 FROM 表1 INNER JOIN 表2 ON 表1.列 <> 表2.列
1.2.3 左连接
-
概述
指以左表为基准进行查询,左表数据会全部显示出来,右表如果和左表匹配的数据则显示相应字段的数据,如果不匹配则显示为NULL;
-
语法
SELECT 列 FROM 表1 LEFT JOIN 表2 ON 表1.列 = 表2.列
1.2.4 右连接
-
概述
指以右表为基准进行查询,右表数据会全部显示出来,左表和右表匹配的数据则显示相应字段的数据,如果不匹配则显示未NULL。
-
语法
SELECT 列 FROM 表1 RIGHT JOIN 表2 ON 表1.列 = 表2.列
1.3 索引
1.3.1 索引的概念
索引存储在内存中,为服务器存储引擎快速找到记录的一种数据结构。索引的主要作用是加快数据查找速度,提高数据库的性能。
1.3.2 索引的分类
- 普通索引:最基本的索引,它没任何限制
- 唯一索引:与普通索引类似,不同的就是索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
- 主键索引:它是一种特殊的唯一索引,用于唯一标识数据表中的某一条记录,不允许有空值,一般使用
primary key
来约束。 - 联合索引(又叫
复合索引
):多个字段上建立的索引,能够加速复合查询条件的检索。 - 全文索引:老版本 MySQL 自带的全文索引只能用于数据库引擎为
MyISAM
的数据表,新版本 MySQL 5.6 的InnoDB
支持全文索引。默认 MySQL 不支持中文全文检索,可以通过扩展 MySQL ,添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文。
1.3.3 索引的优点
- 创建唯一索引,保证数据表中每一行数据的唯一性
- 打打加快数据的检索速度,这也是创建索引的最主要的原因
- 加快表与表之间的连接,特别是实现数据的参考完整性方面特别有意义。
- 在使用分组和排序字句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
1.3.4 索引的缺点
- 创建索引和维护索引都需要耗费时间,并且随着数据量的增加所耗费的时间也会增加
- 索引也需要占用空间,我们知道数据表中的数据也会有最大上限设置,如果我们有大量的索引,索引文件可能会比数据文件更快达到上线值
- 当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度
1.3.5 索引的使用场景
并不是每个字段设置索引就好,也不是索引越多越好,而是需要自己合理的使用
- 对查询频次较高,且数据量比较大的表,建立索引
- 索引字段的选择,最佳候选列应当从 where 子句的条件中提取,如果 where 子句中的组合比较多,那么应该挑选最常用的,过滤效果最好的列的组合
- 在同一值少的列上(字段上)不要建立索引,比如在学生表中“性别”字段上只有男、女两个不同值。相反的,在一个字段上不同值较多适合建立索引。
- 范围查询,左边的列不能使用索引,否则右边的索引也会失效
- 不要在索引字段上使用运算,否则索引也会失效
- 字符串不加引号,造成索引失效
- 尽量使用覆盖索引,避免
select *
这样能提高查询效率 - or 关键字连接,or 前面列有索引,or 后面列没有索引,那么查询的时候前后索引都会失效
2. 性能优化
2.1 避免索引失效
- 如果在查询的时候,使用了复合索引,要遵循最左前缀法则,也就是查询从索引的最左别开始,并不能跳过索引中的列。
- 尽量不要再 where 子句中对字段进行 NULL 值判断,否则将导致引擎放弃使用索引而进行全表扫描
- 不做列运算
where age + 1 = 10
,任何对列的操作都将导致表扫描,它包括数据库教程函数。计算表达式等,都会使索引失效 - 查询 like ,如果是
'%aaa'
也会造成索引失效 - 应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
2.2 SQL 语句调优
- 根据业务场景建立复合索引,只查询业务需要的字段,如果这些字段被索引覆盖,将极大的提高查询效率
- 多表连接的字段上需要建立索引,这样可以极大提高表连接的效率
- where 条件字段上需要建立索引,但 where 条件上不要使用运算函数,以免索引失效
- 排序字段上,因为排序效率低,添加索引能提高查询效率
- 优化 insert 语句:批量列插入数据要比单个列插入数据效率高
- 优化 order by 语句:在使用 order by 语句时,不要使用 select,select 后面要查有索引的列,如果一条 sql 语句中对多个列进行排序,在业务允许情况下,尽量同时用升序或同时用降序
- 优化 group by 语句:在我们对某个字段进行分组的时候,MySQL默认就进行了排序,但是排序并不是我们业务所需的,额外的排序会降低效率,所以在用的时候可以禁止排序,使用 order by null 禁用
- 尽量避免子查询,可以将子查询优化为 join 多表连接查询
2.3 合理的数据库设计
根据数据库三范式来进行表结构的设计。设计表结构时,就需要考虑如何设计才能更有效的查询,遵循数据库三范式:
1NF
:数据表中每个字段都必须是不可拆分的最小单元,也就是确保每一列的原子性;2NF
:满足1NF 后,表中每一列必须有唯一性,都必须依赖于主键;3NF
:满足 2NF 后,表中的每一列只与主键直接相关而不是间接相关(外键也是直接相关),字段没有冗余
注意:没有最好的设计,只有最合适的设计,所以不要过分注重理论。三范式可以作为一个基本依据,不要生搬硬套。有时候可以根据场景合理的规范化:
- 保留冗余字段。当两个或多个表在查询中经常需要连接时,可以在其中一个表上增加若干冗余的字段,以避免表之间的连接过于频繁,一般在冗余列的数据不经常变动的情况下使用。
- 增加派生列。派生列是由表中的其他多个列的计算所得,增加派生列可以减少统计运算,在数据汇总时可以大大缩短运算时间,前提是这个列经常被用到,这就是反#NF。
- 分割表:
- 数据表拆分:主要就是垂直拆分和水平拆分。
- 水平切分:将记录散列到不同的表中,各表的结构完全相同,每次从分表中查询,提高效率。
- 垂直切分:将表中大字段单独拆分到另外一张表,形成一对一的关系
- 字段设计
- 表的字段尽可能用NOT NUL
- 字段长度固定的表查询会更快
- 把数据库的大表按时间或一些标志分成小表
2.4 定位执行效率慢的 sql 语句
- 命令:
show status like ‘Com____’
,通过这条命令,我们可以知道当前数据库是以查询为主还是更新为主。如果是查询为主,就重点查询;如果增删改多就重点优化写入操作。 explain + sql
语句查询sql执行过程,通过执行计划,我们能得到哪些信息:- 哪些步骤花费的成本比较高
- 哪些步骤产生的数据量多,数据量的多少用线条的粗细表示,很直观
- 这条sql语句是否走索引
show profile
分析SQL,可以查看所有sql语句的执行效率(所用时间)。前提是这个命令需要被打开,严格的说也就是打开这个命令后执行的所有sql语句, 它都能记录下执行时间,并展示出来。可以通过这个命令分析哪些sql语句执行效率低。 耗时长,就更有针对性的优化这条sql。- 慢查询日志(常用的工具)
慢查询日志记录了所有执行时间超过参数long_query_time
的sql语句的日志,long_query_time
默认为10秒(可以通过配置文件设置),日志保存在/var/lib/mysql/
目录下,有个slow_query.log
文件。