面试笔记MySQL

MySQL写入顺序与读取顺序

在这里插入图片描述
在这里插入图片描述

7中JOIN

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里MySQL不支持Full Outer Join,我们可以使用union连接(全A+全B)
在这里插入图片描述

在这里插入图片描述
可以使用A独有+B独有

索引

什么是索引

一种帮助数据库高效访问数据的数据结构
排好序的快速查找的数据结构

索引优缺点

优点:加快查询速率
缺点:

  1. 维护索引会耗费数据库资源
  2. 索引占用磁盘空间
  3. 对表进行增删改的时候,因为需要维护索引,会降低性能所以索引不是越多越好

索引分类

1.主键索引

设立为主键后数据库会自动创建索引(Innodb为聚簇索引)

2.单列索引

一个索引只包含单个列,一个表可以有多个单列索引,也叫普通索引

3.唯一索引

索引的列的值必须唯一,但可以是空值,和主键索引的区别:主键索引索引列的值不能为null,而唯一索引可以存在null,但只能存在一个

4.复合索引

多个列组和在一起共同构建的索引

索引的操作

1.查看索引:show index from (表名)

show index from teacher
主键索引创建表时自动创建在这里插入图片描述

普通索引创建

建表后创建 create index index_name on table_name(col)

CREATE index teachername on teacher(tname)
查看一下
show index from teacher
在这里插入图片描述

创建表时创建索引

CREATE table index_text (id VARCHAR(20) PRIMARY KEY, name VARCHAR(20), KEY(name))
show index from index_text

在这里插入图片描述

唯一索引的创建

建表时创建

CREATE table index_text1 (id VARCHAR(20) PRIMARY KEY, name VARCHAR(20), UNIQUE(name))
show index from index_text1

在这里插入图片描述
建表后创建

CREATE UNIQUE index uniqueKey on index_text(name)
show index from index_text

在这里插入图片描述

复合索引创建

建表时创建

create table index_text2(id VARCHAR(20) PRIMARY key,name VARCHAR(20),age INTEGER,key(name,age))
show index from index_text2

在这里插入图片描述
建表后创建

create index aindex on index_text2(id,name,age)
show index from index_text2

在这里插入图片描述
使用复合索引必须基于最左前缀原则:可以用id查,可以id+name,还可以id+name+age,其余情况都不能用
不但使用最左前缀原则,MySQL还会自动调整查询字段以便利用索引:综上,一个字段包含id的,两个字段包含id和name的,三个字段就是都包含的

索引的数据结构

主键索引排了序
innodb默认一页存储16kb
其上还有页目录(也是一个页,但是并不包含数据,只包含指针)
B树

1.所有的键值分布在整棵树中
2.搜索可能在非叶子节点结束(性能逼近二分查找)
3.每棵树最多有m个子树
4.根节点最少有两个子树
5.分支节点至少m/2棵子树(非根非叶子的节点)
6.所有叶子节点都在同一层,每一个节点最6,多有m - 1个key,并且升序排列
实例在这里插入图片描述
比如查找28

  1. 根据根节点找到磁盘1,读入内存(IO)
  2. 比较关键字28在区间(16,34)的范围,找到指针P2
  3. 根据磁盘一的P2找到磁盘三,读入内存(IO)
  4. 比较28所在(27,29)找到磁盘3所在指针P2
  5. 根据磁盘三的P2指针找到磁盘8,读入内存(IO)
  6. 在磁盘8中找到关键字
    缺点1:每个节点都有key,也有data,而每页的存储空间有限,如果data较大的话会导致每个节点存储key数量变小
    缺点2:当存储数据量很大的时候会导致深度很大,也就是有多次IO,影响性能

4.B+树

B+树是在B树上做的优化:

  1. B+树的每个节点可以包含更多的节点:降低了书的高度,将数据范围变为多个区间,区间越多,数据检索越快
  2. 非叶子节点存储key,叶子节点存储key和数据
  3. 叶子节点的两两指针相互连接,顺序查询的性能更高
    支持两种查找:基于主键的范围查找和分页查找或者从根开始随即查找
    在这里插入图片描述

B+树最大的好处是只有叶子节点存储数据,非叶子节点不存储数据,降低了B+树的高度,减少了IO次数(Innodb最顶层根节点为常驻内存
B树非叶子节点就要春初数据,这样每个非叶子节点存储的指针就要少一些,同样多的数据,B树深度更深,增加磁盘IO次数,影响效率。
区别:

  • B+树非叶子节点只存储键值信息
  • B+树的叶子节点之间存在一个链指针
  • B+数据记录都放在叶子节点中

什么是聚簇索引,什么是非聚簇索引

聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。聚簇索引不一定是主键索引,但是主键索引一定是聚簇索引,一张表中只有一个聚簇索引
非聚簇索引(辅助索引):将数据和索引分开存储,索引结构的叶子节点指向了数据对应位置
在这里插入图片描述

小问题:为什么非聚簇索引要用主键而不是行数据物理位置(偏移量)

因为如果使用地址的话当增删后地址有可能发生改变

Innodb中

  • Innodb中使用主键索引,会将主键构成一棵B+树,并且行数据就存储在叶子节点上,若是使用where id = 14,就会按照B+树的算法直接找到对应行数据
  • 对Name列进行条件搜索,需要两个步骤,1:在B+树中检索Name,到达其叶子节点获取对应主键,之后再根据主键索引B+树中再执行一次B+树检索操作,最终达到叶子节点获取整行数据。(使用其他建想这样操作要创建辅助索引(非聚簇索引))
  • 聚簇索引默认主键,若表中没有定义主键,InnoDB会自动选择唯一且非空的索引代替,如果没有这样的索引,InnoDB会隐式定义一个主键作为聚簇索引如果设置了主键所谓聚簇索引又想单独设置聚簇索引,只能先删除主键,之后添加想要的聚簇索引后再恢复主键

MyISAM(不支持事务)

在这里插入图片描述
MyISAM中使用非聚簇索引,非聚簇索引的两颗B+树没什么不同,节点的结构完全一致只是存储的内容不同,主键B+树存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的位置。这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,两个键没有区别和InnoDB的区别就是索引树是独立的,通过辅助键检索也不用访问主键的索引树

Innodb聚簇索引优势

  1. 由于行数据和聚簇索引的叶子节点存储在一起,同一页中有多条行数据,访问同一数据页不同行记录时,已经将页加载到了缓存器中,再次访问时会在内存中完成访问,不必IO=》找到了叶子节点就可以直接返回数据,(使用主键更快)
  2. 辅助索引的叶子节点,存储主键值而不是数据地址值,好处时当行数据进行增删等,索引树节点也需要分裂变化;当我们要炸找的数据在上一次IO没有,需要发生一个新的IO时,可以避免对辅助索引的维护工作,只要维护聚簇索引树(主键那个)即可。另一个好处:辅助索引树叶子节点存放的主键值,减少了辅助索引占用的存储空间

使用注意

最好不用UUID=》不适合排序
建议使用自增(对索引树结构影响小)

为什么自增id

只要索引相邻,那么数据也是相邻的页,同时碎片少

什么没法用索引

1.使用Like关键字(%在右面能用到,但是在左边不行)
2.使用多列索引(复合索引)=》必须使用了第一个字段
3.使用or关键字(如果or前后都有索引,那么会使用索引,但是如果有一个不是,就不能用到索引)

在这里插入图片描述
也会失效

哪些情况建立索引

  1. 自动建立唯一索引
  2. 频繁查找的字段应该建立索引
  3. 查询中与其他表关联的字段,外键关系建立索引
  4. 高并发下倾向创建组合索引
  5. 排序了的字段
  6. 统计或者分组字段

哪些情况不需要建立

  1. 数据少
  2. 经常增删改的表
  3. 很多重复的字段没必要建立

优化

explain:简称执行计划

事务

事务的ACID

A:原子性

事务开始后的所有操作,要么全都做完,要么全都不做,不可能停滞在中间环节,当事务执行过程中报错,事务会回滚到开始前的状态。

C:一致性

事务开始和结束后,数据库的完整性约束并没有被破坏。比如表中唯一字段的某个值,在事务回滚后变为非唯一字段,就违背了一致性

I:隔离性

同一时间,只允许一个事务请求统一数据,不同事物之间彼此没有干扰

D:持久性

事务完成后,事务对数据库的所有更新将会保存到数据库中,不能回滚

MySQL事务隔离级别

在这里插入图片描述
脏读:事务A读取了事务B更新的数据,然后B回滚了,那么A读到的就是脏数据
不可重复读:事务A多次读取同一数据,事务B在事务A多次读取数据过程中,对数据进行了修改并且提交,导致A多次读取同一数据不一致
幻读:A用户使用将数据进行字段修改,此时B用户插入一条原有字段的数据,那么A改后就会发现有一条数据没有动
解决不可重复读的问题只需要锁住满足条件的行,解决幻读要锁住整个表

常见SQL题

1.用一条SQL语句查询出每门课都大于80分的学生姓名
name kecheng fenshu
张三 语文 81
张三 数学 75
李四 语文 76
李四 数学 90
王五 语文 81
王五 数学 100
王五 英语 90

A: select distinct name from table where name not in (select distinct name from table where fenshu<=80)
B:select name from table group by name having min(fenshu)>80

  1. 学生表 如下:
    自动编号 学号 姓名 课程编号 课程名称 分数
    1 2005001 张三 0001 数学 69
    2 2005002 李四 0001 数学 89
    3 2005001 张三 0001 数学 69
    删除除了自动编号不同, 其他都相同的学生冗余信息

A: delete tablename where 自动编号 not in(select min(自动编号) from tablename group by学号, 姓名, 课程编号, 课程名称, 分数)

3.一个叫team的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球队,现在四个球队进行比赛,用一条sql语句显示所有可能的比赛组合.

答:select a.name, b.name
from team a, team b
where a.name < b.name

4.面试题:怎么把这样一个
year month amount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1 m2 m3 m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4

答案
select year,
(select amount from aaa m where month=1 and m.year=aaa.year) as m1,
(select amount from aaa m where month=2 and m.year=aaa.year) as m2,
(select amount from aaa m where month=3 and m.year=aaa.year) as m3,
(select amount from aaa m where month=4 and m.year=aaa.year) as m4
from aaa group by year


5.说明:复制表(只复制结构,源表名:a新表名:b)

SQL: select * into b from a where 1<>1 (where1=1,拷贝表结构和数据内容)
ORACLE:create table b
As
Select * from a where 1=2

[<>(不等于)(SQL Server Compact)
比较两个表达式。 当使用此运算符比较非空表达式时,如果左操作数不等于右操作数,则结果为 TRUE。 否则,结果为 FALSE。]

原表:
courseid coursename score
1 java 70
2 oracle 90
3 xml 40
4 jsp 30
5 servlet 80

为了便于阅读,查询此表后的结果显式如下(及格分数为60):
courseid coursename score mark

1 java 70 pass
2 oracle 90 pass
3 xml 40 fail
4 jsp 30 fail
5 servlet 80 pass

写出此查询语句
select courseid, coursename ,score ,if(score>=60, “pass”,“fail”) as mark from course
7.表名:购物信息
购物人 商品名称 数量
A 甲 2
B 乙 4
C 丙 1
A 丁 2
B 丙 5
……

给出所有购入商品为两种或两种以上的购物人记录

答:select * from 购物信息 where 购物人 in (select 购物人 from 购物信息 group by 购物人 having count(*) >= 2);
8.
info 表
date result
2005-05-09 win
2005-05-09 lose
2005-05-09 lose
2005-05-09 lose
2005-05-10 win
2005-05-10 lose
2005-05-10 lose
如果要生成下列结果, 该如何写sql语句?
   win lose
2005-05-09 2 2
2005-05-10 1 2
答案:
(1) select date, sum(case when result = “win” then 1 else 0 end) as “win”, sum(case when result = “lose” then 1 else 0 end) as “lose” from info group by date;
(2) select a.date, a.result as win, b.result as lose
  from
  (select date, count(result) as result from info where result = “win” group by date) as a
  join
  (select date, count(result) as result from info where result = “lose” group by date) as b
  on a.date = b.date;

找出所有科目成绩都大于某一学科平均水平的学生

在这里插入图片描述

用户每个月的累计访问次数

在这里插入图片描述

计算店铺访问数

在这里插入图片描述

计算订单相关(having)

已知一个表 STG.ORDER,有如下字段:Date,Order_id,User_id,amount。请给出 sql 进
行统计:数据样例:2017-01-01,10029028,1000003251,33.57。

  1. 给出 2017 年每个月的订单数、用户数、总成交金额。
  2. 给出2017年11月的新客户数
    也就是指在11月才有第一笔订单
    (最小的订单时间是2017-11)

求所有用户和活跃用户的总数以及平均年龄(活跃用户指连续两天都有访问记录的用户)

日期、用户、年龄
2019-02-11,test_1,23
2019-02-11,test_2,19
2019-02-11,test_3,39
2019-02-11,test_1,23
2019-02-11,test_3,39
2019-02-11,test_1,23
2019-02-12,test_2,19
2019-02-13,test_1,23
2019-02-15,test_2,19
2019-02-16,test_2,19
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值