很用心的为你写了 9 道 MySQL 面试题
(给ImportNew加星标,提高Java技能)
非关系型数据库和关系型数据库区别,优势比较
MySQL 事务四大特性
-
原子性(Atomicity): 原子性指的就是 MySQL 中的包含事务的操作要么全部成功、要么全部失败回滚,因此事务的操作如果成功就必须要全部应用到数据库,如果操作失败则不能对数据库有任何影响。
-
一致性(Consistency):一致性指的是一个事务在执行前后其状态一致。比如 A 和 B 加起来的钱一共是 1000 元,那么不管 A 和 B 之间如何转账,转多少次,事务结束后两个用户的钱加起来还得是 1000,这就是事务的一致性。 -
持久性(Durability): 持久性指的是一旦事务提交,那么发生的改变就是永久性的,即使数据库遇到特殊情况比如故障的时候也不会产生干扰。 -
隔离性(Isolation):隔离性需要重点说一下,当多个事务同时进行时,就有可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read) 的情况,为了解决这些并发问题,提出了隔离性的概念。
MySQL 常见存储引擎的区别
MySQL 常见的存储引擎,可以使用
SHOW ENGINES
命令,来列出所有的存储引擎
MyISAM 存储引擎的特点
-
不支持事务操作,ACID 的特性也就不存在了,这一设计是为了性能和效率考虑的。 -
不支持外键操作,如果强行增加外键,MySQL 不会报错,只不过外键不起作用。 -
MyISAM 默认的锁粒度是表级锁,所以并发性能比较差,加锁比较快,锁冲突比较少,不太容易发生死锁的情况。 -
MyISAM 会在磁盘上存储三个文件,文件名和表名相同,扩展名分别是 .frm(存储表定义)、.MYD(MYData,存储数据)、MYI(MyIndex,存储索引)。这里需要特别注意的是 MyISAM 只缓存索引文件,并不缓存数据文件。 -
MyISAM 支持的索引类型有 全局索引(Full-Text)、B-Tree 索引、R-Tree 索引 Full-Text 索引:它的出现是为了解决针对文本的模糊查询效率较低的问题。 B-Tree 索引:所有的索引节点都按照平衡树的数据结构来存储,所有的索引数据节点都在叶节点
R-Tree索引:它的存储方式和 B-Tree 索引有一些区别,主要设计用于存储空间和多维数据的字段做索引,目前的 MySQL 版本仅支持 geometry 类型的字段作索引,相对于 BTREE,RTREE 的优势在于范围查找。 -
数据库所在主机如果宕机,MyISAM 的数据文件容易损坏,而且难以恢复。 -
增删改查性能方面:SELECT 性能较高,适用于查询较多的情况
InnoDB 存储引擎的特点
-
支持事务操作,具有事务 ACID 隔离特性,默认的隔离级别是可重复读(repetable-read)、通过MVCC(并发版本控制)来实现的。能够解决脏读和不可重复读的问题。 -
InnoDB 支持外键操作。 -
InnoDB 默认的锁粒度行级锁,并发性能比较好,会发生死锁的情况。 -
和 MyISAM 一样的是,InnoDB 存储引擎也有 .frm文件存储表结构 定义,但是不同的是,InnoDB 的表数据与索引数据是存储在一起的,都位于 B+ 数的叶子节点上,而 MyISAM 的表数据和索引数据是分开的。 -
InnoDB 有安全的日志文件,这个日志文件用于恢复因数据库崩溃或其他情况导致的数据丢失问题,保证数据的一致性。 -
InnoDB 和 MyISAM 支持的索引类型相同,但具体实现因为文件结构的不同有很大差异。 -
增删改查性能方面,如果执行大量的增删改操作,推荐使用 InnoDB 存储引擎,它在删除操作时是对行删除,不会重建表。
MyISAM 和 InnoDB 存储引擎的对比
-
锁粒度方面:由于锁粒度不同,InnoDB 比 MyISAM 支持更高的并发;InnoDB 的锁粒度为行锁、MyISAM 的锁粒度为表锁、行锁需要对每一行进行加锁,所以锁的开销更大,但是能解决脏读和不可重复读的问题,相对来说也更容易发生死锁 -
可恢复性上:由于 InnoDB 是有事务日志的,所以在产生由于数据库崩溃等条件后,可以根据日志文件进行恢复。而 MyISAM 则没有事务日志。 -
查询性能上:MyISAM 要优于 InnoDB,因为 InnoDB 在查询过程中,是需要维护数据缓存,而且查询过程是先定位到行所在的数据块,然后在从数据块中定位到要查找的行;而 MyISAM 可以直接定位到数据所在的内存地址,可以直接找到数据。 -
表结构文件上:MyISAM 的表结构文件包括:.frm(表结构定义),.MYI(索引),.MYD(数据);而 InnoDB 的表数据文件为:.ibd和.frm(表结构定义);
MySQL 基础架构
CREATE TABLE t (i INT) ENGINE = <Storage Engine>;
连接器
mysql -u 用户名 -p 密码
查询缓存
分析器
-
首先,MySQL 会根据你写的 SQL 语句进行解析,分析器会先做 词法分析,你写的 SQL 就是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串是什么,代表什么。 -
然后进行 语法分析,根据词法分析的结果, 语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。如果 SQL 语句不正确,就会提示 You have an error in your SQL syntax
优化器
执行器
SQL 的执行顺序
SELECT DISTINCT
< select_list >
FROM
< left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
< where_condition >
GROUP BY
< group_by_list >
HAVING
< having_condition >
ORDER BY
< order_by_condition >
LIMIT < limit_number >
FROM 连接
ON 过滤
JOIN 连接
WHERE 过滤
-
如果有外部列,ON 针对过滤的是关联表,主表(保留表)会返回所有的列; -
如果没有添加外部列,两者的效果是一样的;
-
对主表的过滤应该使用 WHERE; -
对于关联表,先条件查询后连接则用 ON,先连接后条件查询则用 WHERE;
GROUP BY
HAVING
SELECT
DISTINCT
ORDER BY
什么是临时表,何时删除临时表
-
使用 UNION 查询:UNION 有两种,一种是UNION ,一种是 UNION ALL ,它们都用于联合查询;区别是 使用 UNION 会去掉两个表中的重复数据,相当于对结果集做了一下去重(distinct)。使用 UNION ALL,则不会排重,返回所有的行。使用 UNION 查询会产生临时表。 -
使用 TEMPTABLE 算法或者是 UNION 查询中的视图。TEMPTABLE 算法是一种创建临时表的算法,它是将结果放置到临时表中,意味这要 MySQL 要先创建好一个临时表,然后将结果放到临时表中去,然后再使用这个临时表进行相应的查询。 -
ORDER BY 和 GROUP BY 的子句不一样时也会产生临时表。 -
DISTINCT 查询并且加上 ORDER BY 时; -
SQL 用到 SQL_SMALL_RESULT 选项时;如果查询结果比较小的时候,可以加上 SQL_SMALL_RESULT 来优化,产生临时表 -
FROM 中的子查询; -
EXPLAIN 查看执行计划结果的 Extra 列中,如果使用 Using Temporary 就表示会用到临时表。
MySQL 常见索引类型
-
全局索引(FULLTEXT):全局索引,目前只有 MyISAM 引擎支持全局索引,它的出现是为了解决针对文本的模糊查询效率较低的问题。 -
哈希索引(HASH):哈希索引是 MySQL 中用到的唯一 key-value 键值对的数据结构,很适合作为索引。HASH 索引具有一次定位的好处,不需要像树那样逐个节点查找,但是这种查找适合应用于查找单个键的情况,对于范围查找,HASH 索引的性能就会很低。 -
B-Tree 索引:B 就是 Balance 的意思,BTree 是一种平衡树,它有很多变种,最常见的就是 B+ Tree,它被 MySQL 广泛使用。 -
R-Tree 索引:R-Tree 在 MySQL 很少使用,仅支持 geometry 数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种,相对于 B-Tree 来说,R-Tree 的优势在于范围查找。
varchar 和 char 的区别和使用场景
什么是 内连接、外连接、交叉连接、笛卡尔积
-
外连接(OUTER JOIN):外连接分为三种,分别是左外连接(LEFT OUTER JOIN 或 LEFT JOIN) 、右外连接(RIGHT OUTER JOIN 或 RIGHT JOIN) 、全外连接(FULL OUTER JOIN 或 FULL JOIN)
左外连接:又称为左连接,这种连接方式会显示左表不符合条件的数据行,右边不符合条件的数据行直接显示 NULL
-
内连接(INNER JOIN):结合两个表中相同的字段,返回关联字段相符的记录。
-
笛卡尔积(Cartesian product):我在上面提到了笛卡尔积,为了方便,下面再列出来一下。
SELECT * FROM t_Class a CROSS JOIN t_Student b WHERE a.classid=b.classid
或者不用 CROSS JOIN,直接用 FROM 也能表示交叉连接的效果。
SELECT * FROM t_Class a ,t_Student b WHERE a.classid=b.classid
(select colum1,colum2...columN from tableA ) union (select colum1,colum2...columN from tableB )
或
(select colum1,colum2...columN from tableA ) union all (select colum1,colum2...columN from tableB );
谈谈 SQL 优化的经验
-
查询语句无论是使用哪种判断条件 等于、小于、大于, WHERE 左侧的条件查询字段不要使用函数或者表达式 -
使用 EXPLAIN 命令优化你的 SELECT 查询,对于复杂、效率低的 sql 语句,我们通常是使用 explain sql 来分析这条 sql 语句,这样方便我们分析,进行优化。 -
当你的 SELECT 查询语句只需要使用一条记录时,要使用 LIMIT 1 -
不要直接使用 SELECT *,而应该使用具体需要查询的表字段,因为使用 EXPLAIN 进行分析时,SELECT * 使用的是全表扫描,也就是 type = all。 -
为每一张表设置一个 ID 属性 -
避免在 WHERE 字句中对字段进行 NULL 判断 -
避免在 WHERE 中使用 != 或 <> 操作符 -
使用 BETWEEN AND 替代 IN -
为搜索字段创建索引 -
选择正确的存储引擎,InnoDB 、MyISAM 、MEMORY 等 -
使用 LIKE %abc% 不会走索引,而使用 LIKE abc% 会走索引 -
对于枚举类型的字段(即有固定罗列值的字段),建议使用ENUM而不是VARCHAR,如性别、星期、类型、类别等 -
拆分大的 DELETE 或 INSERT 语句 -
选择合适的字段类型,选择标准是 尽可能小、尽可能定长、尽可能使用整数。 -
字段设计尽可能使用 NOT NULL -
进行水平切割或者垂直分割
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
好文章,我在看❤️