mysql的概念
(1) mysql的架构
客户端请求--->连接器(验证用户身份,给予权限)--->查询缓存(存在则直接返回,不存在则执行后续操作 --->分析器(对SQL进行词法分析和语法分析操作) --->优化器(主要对执行的sql优化选择最优的执行方案方法)--->执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)--->去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)
(2) mysql有哪些引擎
mysql支持的存储引擎有八种,我们常用的两种InnoDB和MyISAM。这两者的区别:
1.InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
2.InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
3.InnoDB 是聚簇索引,MyISAM 是非聚簇索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先通过辅助索引查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
4.InnoDB 不保存表的具体行数,执行select count(*) from table 时需要全表扫描。而 MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
5.InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
(3) mysql的索引 index
索引(Index)是帮助MySQL高效获取数据的,索引的本质是:有序的数据结构
索引的优缺点:
(1)索引的优点:
减少查询需要检索的行数,加快查询速度,避免进行全表扫描,这也是创建索引的最主要的原因。如果索引的数据结构是B+树,在使用分组和排序时,可以显著减少查询中分组和排序的时间。通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
(2)索引的缺点:
当对表中的数据进行增加、删除和修改时,索引也要进行更新,维护的耗时随着数据量的增加而增加。索引需要占用物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
索引常用命令:
|---------------------------------------------------------------------------------------------------------------|
| 创建索引: CREATE [UNIQUE] INDEX indexName ON mytable(username(length)); |
| 实例: CREATE INDEX name_index ON tb_teacher(t_name(20)); ALTER table tb_teacher ADD INDEX phone_index(t_phone); |
| 删除索引: DROP INDEX [indexName] ON mytable; |
| 查看表中的索引 SHOW INDEX FROM tb_teacher; |
索引的类型:
普通索引:仅加速查询
唯一索引:加速查询 + 列值唯一(可以有null)
主键索引:加速查询 + 列值唯一 + 表中只有一个(不可以有null)
组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并 减少回表查询 遵循最左匹配原则
维护成本较高
(4) 如何判断索引是否生效?
在查询语句前加上explain,查看sql语句的执行计划。type:这是重要的列,显示连接使用了何种类型。它在 SQL优化中是一个非常重要的指标。如果type的类型是ALL的话代表语句没有走索引,走了全表扫描。
(5)为什么 Mysql用B+树做索引而不用B-树 ?
因为B+树的data只存储在叶子节点上,B树的所有节点都存储了key和data,B+树的非叶节点不存储data,这样一个节点就可以存储更多的索引值,可以使得树更矮(高度更小),减少I/O次数,磁盘读写代价更低,I/O读写次数是影响索引检索效率的最大因素;
B+树的所有叶结点构成一个有序链表,顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历,相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
(6) 索引失效 ?
(1)使用组合索引没有满足最左匹配原则,也就是最左边的字段一定要在查询条件中。
(2)where 后面有不是索引的字段,但是查询的结果集,超过了总行数 25%,优化器就会认为没有必要走索引了。
(3)加了索引的字段在查询条件中参与运算或者使用了函数
(4)字段的类型不同
mysql发现如果是int类型字段作为查询条件时,它会自动将该字段的传参进行隐式转换, 把字符串转换成int类型。
(5)模糊查询%放前边会造成索引失效
(6)列对比也会造成索引失效
(7)查询条件用or时,如果or的字段中有没有索引的字段那么索引就会失效
解决办法把两个条件分开查询,在使用UNION 进行连接,这样有索引的字段就会走索引。
(7) sql优化
1、查询SQL尽量不要使用select *,而是select具体字段。
理由:只取需要的字段,节省资源、减少网络开销。
select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。
2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1
加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。
- 应尽量避免在where子句中使用or来连接条件,如果or的字段中有没有索引的字段那么索引就会失效。解决办法把两个条件分开查询,在使用UNION 进行连接,这样有索引的字段就会走索引。
- 优化你的like语句
日常开发中,如果用到模糊关键字查询,很容易想到like,但是like很可能让你的索引失效。把%放前面,并不走索引。
5.尽量避免在索引列上使用mysql的内置函数,查询的字段不能使用内置函数否则索引失效
6.应尽量避免在where子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫描.
7、Inner join 、left join、right join,优先使用Inner join,如果是left join,左边表结果尽量小表
8、应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
9、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则
10.对查询进行优化,应考虑在where及order by涉及的列上建立索引,尽量避免全表扫描。
(8) SQL执行顺序
from on join where group by(开始使用select中的别名,后面的语句中都可以使用) avg,sum.... having select distinct
order by limit