MySql相关面试题汇集

​ 扫码关注公众号获取更多资源

在这里插入图片描述

    MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

​ 在创建表的时候需要遵循三范式,三范式是哪些呢?

第一范式:列不可再分

第二范式:行可以唯一区分,主键约束

第三范式:表的非主属性不能依赖与其他表的非主属性 外键约束

且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上。

引擎

​ MySql支持很多数据引擎,包括:myisam、Innodb、Memory、MERGE,但是在日常开发中最常用的是myisam和innodb。

MYISAM:全表锁,拥有较高的执行速度,不支持事务,不支持外键,并发性能差,占用空间相对 较小,对事务完整性没有要求,以select、insert为主的应用基本可以使用这引擎

Innodb:行级锁,提供了具有提交、回滚和崩溃回复能力的事务安全,支持自动增长列,支持外键 约束,并发能力强,占用空间是MYISAM的2.5倍,处理效率相对会差一些

Memory:全表锁,存储在内容中,速度快,但会占用和数据量成正比的内存空间且数据在mysql重 启时会丢失,默认使用HASH索引,检索效率非常高,但不适用于精确查找,主要用于那些内容变 化不频繁的代码表

MERGE:是一组MYISAM表的组合

InnoDB与MyISAM的区别

  • InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交, 这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  • InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  • InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大, 因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的 是数据文件的指针。主键索引和辅助索引是独立的。

  • InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一 个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  • Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

在创建表的时候如何选择数据引擎呢?

​ 如果没有特别的需求,使用默认的即可。

  • MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站。

  • Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高,支持事务和外键。比如OA自动化办公系统。

事务

什么是事务?

​ 多条sql语句,要么全部成功,要么全部失败。

数据库事务特性:

  • 原子性:组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有操作都成功,整个 事务才会提交。任何一个操作失败,已经执行的任何操作都必须撤销,让数据库返回初始状态。

  • 一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的。即数据不会被破坏。如A转账100元给B,不管操作是否成功,A和B的账户总额是不变的。

  • 隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对彼此产生干扰

  • 持久性:一旦事务提交成功,事务中的所有操作都必须持久化到数据库中。

索引

​ 索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息。

    你也可以这样理解:索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,
索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅
速地找到表中的数据,而不必扫描整个数据库。

MySql有4种不同的索引:

  • 主键索引(PRIMARY)

    数据列不允许重复,不允许为NULL,一个表只能有一个主键。

  • 唯一索引(UNIQUE)

    数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。

    • 创建唯一索引:alter table table_name add index unique(column)
    • 创建唯一组合索引:alter table table_name add unique (column1,column2)
  • 普通索引(INDEX)

    • 创建普通索引:alter table table_name add index index_name (column)
    • 创建组合索引:alter table_name add index inde_name(column1,column2)
  • 全文索引(FULLTEXT)

    • 创建全文索引:alter table table_name add fulltext (column)

索引并非是越多越好,创建索引也需要耗费资源,一是增加了数据库的存储空间,二是在插入和删除时要花费较多的时间维护索引

  • 索引加快数据库的检索速度
  • 索引降低了插入、删除、修改等维护任务的速度
  • 唯一索引可以确保每一行数据的唯一性
  • 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能
  • 索引需要占物理和数据空间

SQL优化

  • 查询语句中不要使用select *
  • 尽量减少子查询,使用关联查询代替,left/right/inner join
  • 减少使用in或者not in,使用exists或者not exists或者关联语句查询代替
  • or的查询尽量使用union或者union all替代
  • 尽量避免在where语句中使用!=或者<>操作符,会引起全表扫描
  • 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫 描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null 值,然后这样查询: select id from t where num=0

drop,delete,truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

​ delete和truncate只删除表的数据不删除表的结构
速度,一般来说: drop> truncate >delete
​ delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效; 如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger。

内联接、左外联接、右外联接

  • 内联接(Inner Join):匹配2张表中相关联的记录。
  • 左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录, 右表中未匹配到的字段用NULL表示。
  • 右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录, 左表中未匹配到的字段用NULL表示。在判定左表和右表时,要根据表名出现在Outer Join的左右 位置关系。

并发事务带来的翁

​ 在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一
数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。

  • 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到 数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提 交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确 的。

  • 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那 么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结 果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事 务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。

  • 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束 时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改 导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样 的情况,因此称为不可重复读。

  • **幻读(Phantom read): **幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接 着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了 一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

    不可重复读和幻读区别:
    不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

大表如何优化

​ 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:

  • 限定数据的范围
    务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
  • 读写分离:经典的数据库拆分方案,主库负责写,从库负责读
  • 垂直分区
    根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息, 可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。
    简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说大 家应该就更容易理解了。
    • 垂直拆分的优点: 可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂 直分区可以简化表的结构,易于维护。
    • 垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行 Join来解决。此外,垂直分区会让事务变得更加复杂;
  • 水平分区
    保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了 分布式的目的。 水平拆分可以支撑非常大的数据量。
    水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成 多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据 量过大对性能造成影响。
    水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但 由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好 分库 。
    水平拆分能够 支持非常大的数据量存储,应用端改造也少,但 分片事务难以解决 ,跨节点Join性能较 差,逻辑复杂。《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片,因为拆分会带来逻辑、 部署、运维的各种复杂度 ,一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题 的。如果实在要分片,尽量选择客户端分片架构,这样可以减少一次和中间件的网络I/O。

创建索引的三种方式

创建索引

  • 在执行CREATE TABLE时创建索引
CREATE TABLE user_index2 (
    id INT auto_increment PRIMARY KEY,
    first_name VARCHAR (16),
    last_name VARCHAR (16),
    id_card VARCHAR (18),
    information text,
    KEY name (first_name, last_name),
    FULLTEXT KEY (information),
    UNIQUE KEY (id_card)
);
  • 使用ALTER TABLE命令去增加索引
ALTER TABLE table_name ADD INDEX index_name (column_list);
  • 使用CREATE INDEX命令创建
CREATE INDEX index_name ON table_name (column_list);

删除索引

 alter table table_name drop KEY index_name

删除主键索引

alter table table_name drop primary key 
--主键自增长,不能直接执行此操作(自增长依赖于主键索引),需要取消自增长再行删除
alter table user_index -- 重新定义字段
MODIFY id int,
drop PRIMARY KEY
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值