MySQL核心知识小结
MySQL基础架构了解嘛?能不能给我说一下一个SQL的执行过程。
**答:**在介绍MySQL
架构前,我们不妨通过SQL
执行过程了解一下整体步骤:
连接器
:进行身份认证和权限校验。查询缓存
:建立连接后根据查询语句查看缓存中是否有数据,如果有就直接返回。注意,MySQL8.0
取消了缓存。SQL解析
:解析SQL
语句,分析用户本条SQL
要执行的操作,以及语法是否正确。语句优化
:按照MySQL
认为最优的方式进行SQL
优化。执行
:先判断用户是否具备权限,若有权限则通过存储引擎
查询数据并返回。存储引擎
: 主要负责数据的存储和读取,采用的是插件式架构,常见的存储引擎有MyISAM
、InnoDB
、Memery
等存储引擎。
MySQL支持哪些存储引擎?默认用哪个存储引擎知道嘛?
**答:**这一点我们可以通过下面这段命令查看:
show engines;
查询结果如下图所示,可以看到MySQL
默认采用InnoDB
作为存储引擎。而且InnoDB
是唯一一个支持事务性存储的存储引擎。
嗯,那我怎么查看MySQL的版本呢?
答: 这个嘛,通过下面这段命令就可以知道了
select version();
可以看到笔者使用的MySQL
版本是8
MySQL存储引擎架构了解嘛?
答: MySQL
早起用的存储引擎就是MyISAM
,然后变成InnoDB
,因为MySQL
采用的是插件时存储引擎,所以存储引擎是可以任意切换的,注意存储引擎是针对表的,而不是针对某张数据库的。
如下面这个建表语句,我们就将存储引擎设置为innodb
:
-- 测试脚本
drop table if exists `test`;
create table `test` (
`id` bigint not null comment 'id',
`name` varchar(50) comment '名称',
`password` varchar(50) comment '密码',
primary key (`id`)
) engine=innodb default charset=utf8mb4 comment '测试';
MyISAM和InnoDB有些那区别嘛?
答: 哦,那我先说说MyISAM
:
- 它在性能方便是还行的,例如全文索引、压缩、空间函数等都没问题。
- 只支持表级锁。
- 不支持事务。
- 不支持故障后安全恢复。
- 正是因为不支持行级锁,所以就不支持
mvcc
了。 MyISAM
存储引擎数据和索引文件是分开。- 不支持外键。
InnoDB
:
- 支持行级锁。
- 因为行级锁,所以支持
mvcc
。 - 支持事务,所以并发读写的情况下性能优异。
- 同时支持故障后安全恢复
(依赖redolog)
, - 也支持外键,但是一般情况下我们不太建议开发数据表使用外键。
- 最后一点它索引和数据都在同一个文件上。
你刚刚说到mvcc,能不能给我讲讲这是什么?
碍于篇幅原因,可参考近期整理的这篇文章:
MyISAM和InnoDB如何选择呢?
答: 大部分情况下都建议使用InnoDB
,很多人认为MyISAM
性能要好于InnoDB
,事实并非如此,在高性能MySQL
中提及过:
不要轻易相信“MyISAM 比 InnoDB 快”之类的经验之谈,这个结论往往不是绝对的。在很多我们已知场景中,InnoDB 的速度都可以让 MyISAM 望尘莫及,尤其是用到了聚簇索引,或者需要访问的数据都可以放入内存的应用。
当然你要是不考虑并发性能以及崩溃后数据恢复等情况,可以使用MyISAM
。
MySQL 字段 char 和 varchar 的区别是啥,varchar(30)代表什么意思?(重点)
答: char
定长,如果存储字符串小于char
大小则使用空格填充,由于大小固定,所以查询效率比varchar
快50%
,最多存放255
字符,与编码无关。
varchar
不定长,查询较慢,最多存放65535
个字符。
需要了解的是varchar(30) 代表存30
个字符,其中中文占3
字节,所以30
个字符要占用90
字节。英文是1字节。
我们可以键入下面sql
,这里补充一下char_length
获取的字符长度,有几个字符长度就是多少,length
算的是字节数,查看可以看到length('哈哈')
为6,length('hh')
为2
。
select char_length('哈哈'),length('哈哈');
select char_length('hh'),length('hh');
MySQL查询缓存了解嘛?能不能给我介绍一下?
答: 在MySQL8.0
之前是支持查询缓存的,查询缓存就是为了提高查询性能而诞生的。例如我们执行
select * from table where id=1;
如果开启了查询缓存,那么这一结果就会被缓存起来,下次我们在进行相同查询则会直接从结果中获取。
那我们如何开启查询缓存呢?
答: 在my.cnf中加入下面这段配置即可
query_cache_type=1
query_cache_size=600000
那你知道缓存不命中的几个场景嘛?
答: 大抵有以下几种情况吧:
- 查询
SQL
一样,但是字符串大小写不一样。 - 查询的
SQL
涉及自定义函数、用户变量、临时表、MySQL
库中的表等情况,压根就不会缓存数据。 - 一旦我们进行数据更新或者表结构调整的情况,那么缓存也会被清理掉。
- 缓存空间满了,会根据缓存回收算法去清空
SQL
缓存。
那你知道MySQL缓存有什么缺点嘛?
答: MySQL8.0
移除查询缓存就说明这个机制根本很大的优势,如果我们开启缓存大量的查询都在缓存中,无论是维护还是移除都会带来很大的开销。所以如果你在MySQL5.0+
使用缓存时,若希望某张表不进行缓存,就可以使用下面这样的SQL
避免使用缓存
select sql_no_cache count(*) from usr;
MySQL事务
由于事务涉及知识较多,可以参考笔者写的这篇文章
MySQL磁盘爆满了,要怎么解决呢?
答: 首先我们要知道磁盘爆满的原因:
数据量暴增
这就得多方面考虑了,为什么会暴增,暴增是否因为业务涉及不合理,我们是否可以从功能上进行优化。实在不行就只能扩容了。
日志
日志导致容量暴增基本就bin log
或者error
日志没有及时清理了,这种情况我们只能删除一些bin log
即可了。
临时文件
数据库某些查询结果都会放在内存的,当内存空间不足时就会为查询结果生成一个临时文件,供用户使用。但是高并发+大量慢查询
很可能导致这些临时文件未能及时清除进而出现容量爆满问题。
解决方式也很简单,首先找到临时文件的位置
show variables like 'tmpdir'
然后到达对应的位置将临时文件内容置空
echo '' >> host-xxxxx.log
注意我们此时可能还需清除慢查询SQL
,查看是否有time
数据很大的慢查询
SELECT id, `state`, user,host,time,`INFO` FROM information_schema.processlist where state IS NOT NULL and state <> "" ORDER BY time desc;
如果有则杀掉
SELECT concat('kill ', id, ';') FROM information_schema.processlist where user = 'HispaceCMS' and `COMMAND` = 'Query' and state IS NOT NULL and state <> '' and DB is not null and time > 1000 ORDER BY time desc
知不知道MySQL中的count(*)、count(1)、count(列名)的区别
回答这个问题我们不妨做个实验,首先建立数据表
create table count_test(
id int
)
insert into count_test values(1);
insert into count_test values(2);
insert into count_test values(null);
然后键入以下SQL
进行查询,可以看到前面两条不会忽略null
值,最后count(列名)
会忽略null
值。
select count(*),count(1),count(id) from count_test;
而性能方便,如果有主键的话,count(列名)
最优。如果没有主键索引且表中有多列的话,count(1)
最优,如果表只有1列的话,count(*)
最优。
一些常见的笔试题
MySQL查询系统时间的函数是
select sysdate();
请描述一下可以从哪几个方面进行数据库优化
- 用分片键
(如果有涉及分库分表的话)
- 优化缓存:可以提高
PGA
和SGA
分区大小等手段。 - 优化索引:建立索引方式可以参考上文。
- 优化
SQL
:尽可能让SQL
走索引,不要用*
触发没必要的回表操作。
请设计一张单科目的学生成绩表
drop table xx_score;
create table xx_score(
id int ,
socre float,
level char(1)
);
insert into xx_score values (1,99,'A');
insert into xx_score values (2,94,'A');
insert into xx_score values (3,93,'A');
insert into xx_score values (4,92,'A');
insert into xx_score values (5,91,'A');
insert into xx_score values (6,89,'B');
insert into xx_score values (7,70,'C');
insert into xx_score values (8,71,'C');
insert into xx_score values (9,76,'C');
- 查询成绩大于平均成绩的学生人数。
select
count(1)
from
xx_score
where
socre > (
select
avg(socre)
from
xx_score);
- 查询70分以上的学生人数,每10分一个区间。
select level,count(1) from xx_score group by level;
参考文献
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!