C# 面试手册

MySQL

为什么要一定要设置主键?

其实这个不是一定的,有些场景下,小系统或者没什么用的表,不设置主键也没关系,mysql最好是用自增主键,主要是以下两个原因:如果定义了主键,那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则innodb 会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则innodb 会选择内置6字节长的ROWID作为隐含的聚集索引。所以,反正都要生成一个主键,那你还不如自己指定一个主键,提高查询效率!

自增主键用完了怎么办?

在mysql中,Int整型的范围(-2147483648~2147483648),约20亿!因此不用考虑自增ID达到最大值这个问题。而且数据达到千万级的时候就应该考虑分库分表了。

为什么不直接存储图片、音频、视频等大容量内容?

我们在实际应用中,都是文件形式存储的。mysql中,只存文件的存放路径。虽然mysql中blob类型可以用来存放大容量文件,但是,我们在生产中,基本不用!主要有如下几个原因:

  • Mysql内存临时表不支持TEXT、BLOB这样的大数据类型,如果查询中包含这样的数据,查询效率会非常慢。
  • 数据库特别大,内存占用高,维护也比较麻烦。
  • binlog太大,如果是主从同步的架构,会导致主从同步效率问题!因此,不推荐使用blob等类型!

Sql和my sql的区别是什么?

Sql是结构化查询语言,my sql是一个关系型数据库。

主键是用自增还是UUID?

最好是用自增主键,主要是以下两个原因:

  1. 如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。
  2. 如果使用非自增主键(如uuid),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到索引页的随机某个位置,此时MySQL为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成索引碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

不过,也不是所有的场景下都得使用自增主键,可能场景下,主键必须自己生成,不在乎那些性能的开销。那也没有问题。

CHAR 和 VARCHAR 的区别?

char和varchar类型声明长度表示用户想保存的最大字符数,其中char(M)定义的列的长度为固定的,M的取值可以0-255之间,当保存char值时,在它们的右边填充空格以达到指定的长度。

当检索到char值时,尾部的空格被删除掉。在存储或检索过程中不进行大小写转换。char存储定长数据很方便,char字段上的索引效率很高。

varchar(M)定义的列的长度是可变长度字符串,在MySQL5.0以上的版本中,varchar的数据类型长度支持到了65535,因为起始位和结束位占去了3个字节,所以其整体最大长度为65532字节(varchar的最大有效长度由最大行大小和使用的字符集确定)。

同样在char和varchar尾部加空格,检索时char类型后的被删掉,而varchar类型的保存。

字段为什么要定义为NOT NULL?

一般情况,都会设置一个默认值,不会出现字段里面有null,又有空的情况。主要有以下几个原因:

  1. 索引性能不好,Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。

  2. 如果某列存在null的情况,可能导致count() 等函数执行不对的情况。

  3. sql 语句写着也麻烦,既要判断是否为空,又要判断是否为null等。

时间字段用什么类型?

这个看具体情况和实际场景,timestamp ,datatime ,bigint 都行!把理由讲清楚就行!

timestamp,该类型是四个字节的整数,它能表示的时间范围为1970-01-01 08:00:01到2038-01-19 11:14:07。2038年以后的时间,是无法用timestamp类型存储的。但是它有一个优势,timestamp类型是带有时区信息的。一旦你系统中的时区发生改变,例如你修改了时区,该字段的值会自动变更。这个特性用来做一些国际化大项目,跨时区的应用时,特别注意!

datetime,占用8个字节,它存储的时间范围为1000-01-01 00:00:00 ~ 9999-12-31 23:59:59。显然,存储时间范围更大。但是它坑的地方在于,它存储的是时间绝对值,不带有时区信息。如果你改变数据库的时区,该项的值不会自己发生变更!

bigint,也是8个字节,自己维护一个时间戳,查询效率高,不过数据写入,显示都需要做转换。

mysql有关权限的表都有哪几个?

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:

  • user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。
  • db权限表:记录各个帐号在各个数据库上的操作权限。
  • table_priv权限表:记录数据表级的操作权限。
  • columns_priv权限表:记录数据列级的操作权限。
  • host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。

MySQL数据库cpu飙升到100%的话他怎么处理?

列出所有进程 show processlist 观察所有进程 多秒没有状态变化的(干掉)

查看慢查询,找出执行时间长的sql;

explain分析sql是否走索引,sql优化;

检查其他子系统是否正常,是否缓存失效引起,需要查看buffer命中率;

MyISAM索引与InnoDB索引的区别?

InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。

InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。

MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。

InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效

数据表损坏的修复方式有哪些?

使用 myisamchk 来修复,具体步骤:

  1. 修复前将mysql服务停止。
  2. 打开命令行方式,然后进入到mysql的/bin目录。
  3. 执行myisamchk –recover 数据库所在路径/*.MYI

使用repair table 或者 OPTIMIZE table命令来修复,REPAIR TABLE table_name 修复表 OPTIMIZE TABLE table_name 优化表 REPAIR TABLE 用于修复被破坏的表。

OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,使用了OPTIMIZE TABLE命令后这些空间将被回收,并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)