MySQL面试题
1.Mysql逻辑架构
1.客户端请求:客户端/服务端通信协议是“半双工”的,再任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据 2.查询缓存:在解析一个查询语句前,如果缓存是打开的,那么MySQL会检查这个查询语句是否命中查询缓存中的数据。 3.语法解析和预处理:通过语法规则来验证和解析,比如列是否存在。 4.查询优化:一条查询可以有很多种执行方式,最后都返回相应的结果。优化器的作用就是找到这其中最好的执行计划。 5.查询执行引擎:整个执行过程的大部分操作均是通过调用存储引擎实现的接口来完成 6.返回结果:即使查询不到数据,MySQL仍然会返回这个查询的相关信息,比如该查询影响到的行数以及执行时间等等。
2.存储引擎InnoDB和MyISAM的区别
InnoDB | MyISAM | |
事务 | 支持事务 | 不支持事务 |
外键 | 支持外键 | 不支持外键 |
聚簇索引 | InnoDB 是聚簇索引,聚簇索引的文件存放在主键索引的叶子节点上,但是辅助索引需要两次查询 | MyISAM 是非聚集索引,数据和索引是分离的,索引保存的是数据文件的指针 |
具体行数 | InnoDB 不保存表的具体行数,执行select count(*) from table 时需要全表扫描 | MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可 |
最小的锁粒度 | InnoDB 最小的锁粒度是行锁 | MyISAM 最小的锁粒度是表锁 |
3.CHAR 和 VARCHAR 的区别
char是固定长度,varchar长度可变;存储时,前者不管实际存储数据的长度,直接按 char 规定的长度分配存储空间,而后者会根据实际存储的数据分配最终的存储空间
4.BLOB和TEXT有什么区别
BLOB是一个二进制对象。有四种类型的BLOB:TINYBLOB、BLOB、MEDIUMBLO和 LONGBLOB TEXT是一个不区分大小写的字符数据对象。四种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。
5.Mysql索引原理
1.InnoDB 会自动创建名为PRIMARY的特殊索引,也就是聚簇索引。它实际上就是按主键构建的一个B+树,叶子节点存放的是数据行记录;非聚簇索引的叶子节点中存放的是键值和主键值。使用辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据 2.MyISAM是非聚簇索引,数据和索引存储是分离的,索引保存的是数据文件的指针 3.MyISAM 和 InnoDB 存储引擎,都使用 B+Tree的数据结构,所有的数据都存放在叶子节点上,且把叶子节点通过指针连接到一起,形成了一条数据链表,以加快相邻数据的检索效率。
6.count(*) 和 count(1)和count(列名)的区别
count(*)和count(1)执行的效率是完全一样的。 count(*)的执行效率比count(col)高,因此可以用count(*)的时候就不要去用count(col)。 count(col)的执行效率比count(distinct col)高,不过这个结论的意义不大,这两种方法也是看需要去用。
7.MySQL中 in和 exists 的区别
IN:适合外表大,因为条件可用走索引 select * from tabA where tabA.x in (select x from tabB where y>0 ); 执行过程: (1)执行tabB表的子查询,得到结果集B,可以使用到tabB表的索引y; (2)执行tabA表的查询,查询条件是tabA.x在结果集B里面,可以使用到tabA表 的索引x。 IN()查询是从缓存中取数据 EXISTS: 适合外表小,因为要全表扫描 select * from tabA where exists (select 1 from tabB where y>0); 执行过程: (1)先将tabA表所有记录取到。 (2)逐行针对tabA表的记录,去关联tabB表,判断tabB表的子查询是否有返回数据,(5.5之后的版本)使用Block Nested Loop(Block 嵌套循环)。 (3)如果子查询有返回数据,则将tabA当前记录返回到结果集。 tabA相当于取全表数据遍历,tabB可以使用到索引。 EXISTS()查询是将主查询的结果集放到子查询中做验证,根据验证结果是true或false来决定主查询数据结果是否得以保存。
8.Mysql事务原理(腾讯面试)
见 MySQL 事务
9.Mysql锁机制
10.delete 与 truncate的区别
(1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从中删除所有的数表据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。 (2) 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。 (3) truncate删除表中数据,再插入时自增长id又从1开始;delete删除表中数据,可以加where字句
11.Mysql日志文件
12.Mysql常规优化
1. 避免使用。select * 需要什么信息,就查询什么信息,查询的多了,查询的速度肯定就会慢 2. 当你只需要查询出一条数据的时候,要使用 limit 1 比如你要查询数据中是否有男生,只要查询一条含有男生的记录就行了,后面不需要再查了,使用Limit 1 可以在找到一条数据后停止搜索 3. 建立高性能的索引。索引不是随便加的也不是索引越多越好,更不是所有索引对查询都有效 4. 建数据库表时,给字段设置固定合适的大小。字段不能设置的太大,设置太大就造成浪费,会使查询速度变慢 5. 要尽量使用not null 6. EXPLAIN 你的 SELECT 查询。使用EXPLAIN,可以帮助你更了解MySQL是如何处理你的sql语句的, 你可以查看到sql的执行计划,这样你就能更好的去了解你的sql语句的不足,然后优化语句. 7. 在Join表的时候,被用来Join的字段,应该是相同的类型的,且字段应该是被建过索引的,这样,MySQL内部会启动为你优化Join的SQL语句的机制。 8. 如果你有一个字段,比如“性别”,“国家”,“民族”, “省份”,“状态”或“部门”,这些字段的取值是有限而且固定的,那么,应该使用 ENUM 而不是 VARCHAR。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。 9. 垂直分割。将常用和有关系的字段放在相同的表中,把一张表的数据分成几张表 这样可以降低表的复杂度和字段的数目,从而达到优化的目的
10. 优化where查询
a.避免在where子句中对字段进行表达式操作 比如: select 列 from 表 where age*2=36; 建议改成 select 列 from 表 where age=36/2;
b.应尽量避免在 where 子句中使用 !=或<> 操作符,否则将引擎放弃使用索引而进行全表扫描。
c.应尽量避免在 where 子句中对字段进行 null 值 判断
d.应尽量避免在 where 子句中使用 or 来连接条件
11. 不建议使用%前缀模糊查询,这种查询会导致索引失效而进行全表扫描 例如LIKE “%name”或者LIKE “%name%这两种都是不建议的.但是可以使用LIKE “name%”。 对于LIKE “%name%,可以使用全文索引的形式
12. 要慎用in和 not in 例如:select id from t where num in(1,2,3) 建议改成 select id from t where num between 1 and 3 对于连续的数值,能用 between 就不要用 in 了
13.什么是存储过程?有哪些优缺点
存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。
存储过程调用:call sp_name[(传参)]
14.数据库三范式
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解; 第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性; 第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。。
15.Mysql分区
见 MySQL 分区
16.Mysql主从复制
1、主服务器上面的任何修改都会通过自己的 I/O tread(I/O 线程)保存在二进制日志 Binary log 里面。 2、从服务器上面也启动一个 I/O thread,连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log(中继日志)里面。 3、从服务器上面同时开启一个 SQL thread 定时检查 Realy log(这个文件也是二进制的),如果发现有更新立即把更新的内容在本机的数据库上面执行一遍