暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

面试题整理-MYSQL篇

猿码记 2020-02-10
231



















1.Mysql的存储引擎,MyISAM和InnoDB的区别。

  • MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.

  • MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快.

  • InnoDB不支持FULLTEXT(全文索引) 类型的索引.

  • InnoDB 中不保存表的具体行数,也就是说执行 :select count(*) from table时, InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可.

  • 对于AUTO_INCREMENT(递增)类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

  • DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

  • Load Table From Master 操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用.

  • MyISAM支持表锁,InnoDB支持行锁。

2.delete、drop、truncate区别

  • truncate 和 delete只删除数据,不删除表结构 ,drop删除表结构,并且释放所占的空间。

  • 删除数据的速度,一般来说: drop> truncate > delete

  • delete属于DML语言,需要事务管理,commit之后才能生效。drop和truncate属于DDL语言,操作立刻生效,不可回滚

使用场合

  1. 当你不再需要该表时,用drop;

  2. 当你仍要保留该表,但要删除所有记录时, 用truncate;

  3. 当你要删除部分记录时(always with a where clause), 用 delete.

对于有主外键关系的表,不能使用truncate而应该使用不带where子句的delete语句,由于truncate不记录在日志中,不能够激活触发器

3.优化MYSQL数据库的方法

  1. 选取最适用的字段属性,尽可能减少定义字段长度,尽量把字段设置NOT NULL,例如'省份,性别',最好设置为ENUM

  2. 使用连接(JOIN)来代替子查询

  3. 使用联合(UNION)来代替手动创建的临时表

  4. 事务处理: 保证数据完整性,例如添加和修改同时,两者成立则都执行,一者失败都失败。

  5. 锁定表,优化事务处理

  6. 建立索引

  7. 优化查询语句

    1. 避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

    2. 避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。

    3. 避免在 where子句中对字段进行null值判断,会引起全表扫描,因此字段都应设置为NOT NULL,将来查询的时候就不用去比较NULL值。

    4. 避免在where子句中使用or来连接条件,会引起全表扫描。

    5. in 和 not in 也要慎用,否则会导致全表扫描。

    6. 避免在 where 子句中对字段进行表达式操作。

    7. 索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,一个表的索引数最好不要超过6个。

    8. 任何地方都不要使用 select * from t ,用具体的字段列表代替"*”,不要返回用不到的任何字段。

    9. 通过explain查询和分析SQL的执行计划 

4.mysql_fetch_row()和mysql_fetch_array()有什么分别?

  1. mysql_fetch_row() # 返回的结果集是索引数组。

  2. mysql_fetch_assoc() # 返回的结果集是关联数组

  3. # 既可以返回索引数组也可以返回关联数组,

  4. # 取决于它的第二个参数 MYSQL_BOTH MYSQL_NUM MYSQL_ASSOC 默认为MYSQL_BOTH

  5. mysql_fetch_array()

5.php访问数据库有哪几步?

1.连接数据库服务器:

  1. mysql_connect('数据库服务器的主机名或ip','数据库服务器的用户名','数据库服务器的密码');

2.选择数据库:

  1. mysql_select_db(数据库名);

3.设置从数据库提取数据的字符集:

  1. mysql_query("set names utf8");

4.执行sql语句:

  1. mysql_query(sql语句);

5.关闭结果集,释放资源:

  1. mysql_free_result($result);

6.关闭与数据库服务器的连接:

  1. mysql_close($link);

6.表设计三大范式

  1. 第一范式(原子性):所有字段值都是不可分解的原子值。

  2. 第二范式(在第一范式的基础上):确保表中的每列都和主键相关,即一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

  3. 第三范式(在第二范式的基础上):确保每列都和主键列直接关联,而不是间接相关。

7.索引类型

1.普通索引(index):

  1. # 创建:

  2. CREATE INDEX <索引名> ON tablename (索引字段)

  3. # 修改:

  4. ALTER TABLE tablename ADD INDEX [索引名] (索引字段)

  5. # 创建指定索引:

  6. CREATE TABLE tablename([...],INDEX[索引名](索引字段))

2.唯一索引(unique):在普通索引的基础上,会进行排除重复值

  1. #创建:

  2. CREATE UNIQUE <索引名> ON tablename (索引字段)

  3. #修改:

  4. ALTER TABLE tablename ADD UNIQUE [索引名] (索引字段)

  5. #创指定索引:

  6. CREATE TABLE tablename([...],UNIQUE[索引名](索引字段))

3.主键(primary key):和唯一索引的区别在于一个表里只能有一个主键索引,但是唯一索引可以有多个

  1. #它是唯一索引,一般在创建表时建立

  2. CREATA TABLE tablename ([...],PRIMARY KEY[索引字段])

4.联合索引

  1. # 语法:

  2. ALTER TABLE table_name ADD INDEX index_name ( column1, column2, column3 )

5.全文索引 (fulltext)

版本支持

  • MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;

  • MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;

  • 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。

创建全文索引

  1. # 创建表时创建全文索引

  2. CREATE TABLE `user` (

  3.  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',

  4.  `phone` char(11) NOT NULL DEFAULT '' COMMENT '手机号',

  5.  `name` varchar(30) NOT NULL DEFAULT '' COMMENT '用户名',

  6.  `address` text NOT NULL COMMENT '地址',

  7.  PRIMARY KEY (`id`),

  8.  # 创建全文索引列

  9.  FULLTEXT KEY address_fulltext(address)

  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4  COMMENT='用户帐号表';

  11. # 在已存在的表上创建全文索引

  12. CREATE fulltext index name_fulltext on `user`(address);

  13. # 通过SQL语句 ALTER TABLE 创建全文索引

  14. alter table `user` add FULLTEXT index name_fulltext(address);


使用全文索引和常用的模糊匹配使用 like + % 不同,全文索引有自己的语法格式,使用 match 和 against 关键字,比如: 

  1. SELECT * from `user` WHERE MATCH(`address`) against('碧园春小区')

match() 函数中指定的列必须和全文索引中指定的列完全相同,否则就会报错,无法使用全文索引,这是因为全文索引不会记录关键字来自哪一列。如果想要对某一列使用全文索引,请单独为该列创建全文索引。

问题: 普通索引/唯一索引/主键索引 哪个速度更快?

速度是一样的快,因为三者都是采用btree二叉树算法进行查找。

8.索引算法

1.BTREE算法

Innodb和MyISAM默认的索引是BTREE索引,采用二叉树算法,左边的树枝小于根节点关键词,右边大于根节点,两边的树的深度不大于1,从而降低时间复杂度。

2.HASH算法

Mermory默认的索引是Hash索引,Hash索引只能用于HASH值比较,例如=,<> 操作符,不像BTREE索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTREE索引。

为什么不默认采用HASH索引呢?

HASH只能用在=和<>上,所以功能受限,所以默认采用BTREE。

9.insert和replace的区别

replace into 跟 insert 功能类似,不同点在于: replace into 首先尝试插入数据到表中, 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。否则,直接插入新数据。

要注意的是:插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。

  • MySQL replace into 有三种形式:

  1. replace into tbl_name(col_name, ...) values(...)

  2. replace into tbl_name(col_name, ...) select ...

  3. replace into tbl_name set col_name=value, ...

前两种形式用的多些。其中 "into” 关键字可以省略,不过最好加上 "into”,这样意思更加直观。另外,对于那些没有给予值的列,MySQL 将自动为这些列赋上默认值

10.事务操作数据库的四大特性(ACID)

  • 原子性 (Atomicity):就是事务的所包含的所有操作,要么全部成功,要么全部失败回滚。

  • 一致性 (Consistency):简单来说就是在事务执行前和执行后,必须保持数据的一致。

  • 隔离性 (Isolation):一个事务执行的过程当中,不能被其他的事务干扰。比如有事务A和事务B,相对于A来说,B想要执行,要么在我执行之前执行,要么在我执行完毕之后,你再开始执行.

  • 持久性 (Durability):事务被提交之后,他就被永久的存储到了数据库当中。

11.不考虑事务的隔离性所引发的问题

脏读:一个事务读取到了一个未提交的事务的数据。不可重复读:在读取数据库的某条数据的时候返回了不同的值,造成这个结果的原因是因为我们在查询了一次之后准备进行第二次查询的这个间隔之间,对我们要进行查询的这条数据进行了修改操作,从而导致两次读取的数据不一致。

脏读和不可重复读的区别:脏读是一个事务读取到了一个未提交事务的脏数据,而不可重复读是一个数据读取了一个已经提交了的事务的数据。

虚读(幻读):出现幻读不是对一条数据的操作而产生的问题,而是操作多条数据产生的问题,例如:事务A想要对一张表中的某一字段的值进行修改,假设有一个字段的值全部为1,事务A现在想要将1全部修改为2,在提交事务之后,事务B接着又进行了一个操作,在这张表中添加了一个字段,值全部为1。那么这时候操作事务A的用户在查看的时候,会发现还有一行数据没有进行修改,其实这是事务B在他查看之前添加的。

幻读和不可重复读都是读取了一个已经提交的事务,而脏读是读取了一个未提交的事务。不同的是不可重复读查询的是同一条数据,而虚读查询的是批量数据。

12.事务的四种隔离级别

  • Serializable (序列化):可避免脏读、不可重读读、幻读的发生

  • Repeatable-read (可重复读):可避免脏读、不可重复读的发生。

  • Read-committed (读已提交):可避免脏读的发生。

  • Read-uncommitted (读未提交):最低级别,任何情况都无法保证。

以上四种的隔离级别最高的Serializable,最低的是Read uncommitted,级别越高,虽然安全级别越高,但是执行的效率就越低,MySQL中默认的隔离级别是:Repeatable read(可重复读),oracle默认的隔离级别是:Read committed(读已提交)。

这里需要注意的是,mysql支持以上四种隔离级别,但是oracle只支持Serializable(串行化)和Read committed(读已提交)这两种隔离级别。

  • MySQL中查看当前的事务隔离界别

  1. select @@tx_isolation

  • 设置mysql的隔离级别

  1. set tx_isolation='read-uncommitted'

记住:设置数据库的隔离级别一定要是在开启事务之前!

隔离级别的设置只对当前的链接有效。对于MySQL窗口来说,一个窗口就是一个链接,当前设置的事务隔离级别只对当前的窗口有效。

13.CHAR和VARCHAR的区别

1.存储方式
  • 当值存储在CHAR字段中时,剩余的字符将用空格填充; 例如:一个字段是 name char(5),并且您要存储只是"tom",则实际值将存储为"tom "

  • 与CHAR不同,VARCHAR只占用基于存储的数据的空间

  • varchar类型的实际长度是它的值的实际长度+1,这一个(也可能是两)字节用于保存实际使用了多大的长度

  • char的存储方式是:英文字符占1个字节,汉字占用2个字节;varchar的存储方式是:英文和汉字都占用2个字节,两者的存储数据都非unicode的字符数据

2.数据检索

如果CHAR字段的数据较短时,会经过空格填充,所以查询出来的结果需删除尾随空格。

3.存储上限
  • char(n),n最大255。

  • varchar(n),n最大65535,另外,按照字符集,不能超过65525字节。这65535字节不能全用来存数据,因为有1-2字节要用来存占用长度,255字节以下用1字节存储长度,255字节以上用2字节存储长度。

  • text,上限65535字节,再多也能存,因为还有mediumtext上限2^24-3字节大概16m,longtext上限2^32-4字节大概4G。

4.性能对比

按照查询速度:char最快, varchar次之,text最慢

  • char,定长,基本没有碎片,索引速度极快。

  • varchar,不定长,索引速度没有char快。理论上可以添加全部索引,但是数据长度太大时索引也会截取数据前面的一部分。

  • text,不定长,速度慢,索引只能是前缀索引。

5.不同存储引擎对CHAR和VARCHAR的使用
  • MyISAM 存储引擎:建议使用固定长度的数据列代替可变长度的数据列。

  • MEMORY 存储引擎:目前都使用固定长度的数据行存储,因此无论使用 CHAR 或 VARCHAR 列都没有关系。两者都是作为 CHAR 类型处理。

  • InnoDB 存储引擎:建议使用 VARCHAR 类型。对于 InnoDB 数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),因此在 本质上,使用固定长度的 CHAR 列不一定比使用可变长度 VARCHAR 列性能要好。因而,主要的性能因素是数据行使用的存储总量。由于 CHAR 平均占用的空间多于 VARCHAR,因此使 用 VARCHAR 来最小化需要处理的数据行的存储总量和磁盘 I/O 是比较好的。

14.BLOB和TEXT有什么区别

  • 二者之间的主要差别是 BLOB 能用来保存二进制数据(比如照片),而TEXT只能保存字符数据

  • TEXT值是大小写不敏感的

  • BLOB值进行排序和比较时区分大小写

15.NOW()和CURRENT_DATE() 有什么区别

  • NOW() 命令用于显示当前年份、月份、日期、小时、分钟和秒。

  • CURRENT_DATE() 仅显示当前年份、月份和日期。

16.如何理解超键、候选键、主键、外键

1. 主键(Primary Key):对数据库表中的每一行数据进行唯一标识。

  • 任意两行的主键值都不同

  • 包含主键值的列从不修改或更新

  • 主键值不能重用

  • 使用PRIMARY KEY进行标识

2. 外键(foreign key):是表中的一列,其值必须在另一个表的主键中。3.超键(Super Key):在关系中能惟一标识元组(数据库中的一条记录)的属性集称为关系模式的超键。比如:一张学生信息表,学生表中含有学号或者身份证号的任意组合都为此表的超键。如:(学号)、(学号,姓名)、(身份证号,性别)等。4.候选键(Candidate Key):不含有多余属性的超键称为候选键。也就是在候选键中,若要再删除属性,就不能唯一标识元组了。比如:学生表中的候选键为:(学号)、(身份证号)。

17.一条SQL语句在MySQL中是如何执行的?

查询语句的执行流程如下: 

权限校验(如果命中缓存)--> 查询缓存 -->分析器-->优化器-->权限校验-->执行器-->引擎

更新语句执行流程如下:

分析器--> 权限校验--> 执行器--> 引擎--> redo log(prepare 状态--> binlog--> redo log(commit状态)

18.什么是存储过程?

存储过程是一些预编译的SQL语句。

  1. 更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。

  2. 存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。

19.什么是视图?以及视图的使用场景有哪些?

  1. 视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

  2. 只暴露部分字段给访问者,所以就建一个虚表,就是视图。

  3. 查询的数据来源于不同的表,而查询者希望以统一的方式查询,这样也可以建立一个视图,把多个表查询结果联合起来,查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异。

20.数据库的乐观锁和悲观锁是什么?

数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。

悲观锁: 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。

乐观锁: 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

21.什么是触发器,MySQL中都有哪些触发器?

触发器是指一段代码,当触发某个事件时,自动执行这些代码。在MySQL数据库中有如下六种触发器:

  • Before Insert

  • After Insert

  • Before Update

  • After Update

  • Before Delete

  • After Delete



长按二维码获取最新状态


“阅读原文”我们一起进步
文章转载自猿码记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论