教育改变生活

标题: mysql面试题 [打印本页]

作者: 李玮    时间: 2020-4-23 17:40
标题: mysql面试题


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

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

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

4:主键为什么不推荐有业务含义?
最好是主键是无意义的自增ID,然后另外创建一个业务主键ID,
因为任何有业务含义的列都有改变的可能性,主键一旦带上了业务含义,那么主键就有可能发生变更。主键一旦发生变更,该数据在磁盘上的存储位置就会发生变更,有可能会引发页分裂,产生空间碎片。
还有就是,带有业务含义的主键,不一定是顺序自增的。那么就会导致数据的插入顺序,并不能保证后面插入数据的主键一定比前面的数据大。如果出现了,后面插入数据的主键比前面的小,就有可能引发页分裂,产生空间碎片。

5:货币字段用什么类型?
货币字段一般都用 Decimal类型,
float和double是以二进制存储的,数据大的时候,可能存在误差。看下面这个图就明白了:



6:时间字段用什么类型?
这个看具体情况和实际场景,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个字节,自己维护一个时间戳,查询效率高,不过数据写入,显示都需要做转换。这种存储方式的具有 Timestamp 类型的所具有一些优点,并且使用它的进行日期排序以及对比等操作的效率会更高,跨系统也很方便,毕竟只是存放的数值。缺点也很明显,就是数据的可读性太差了,你无法直观的看到具体时间。

7:为什么不直接存储图片、音频、视频等大容量内容?
我们在实际应用中,都是文件形式存储的。mysql中,只存文件的存放路径。虽然mysql中blob类型可以用来存放大容量文件,但是,我们在生产中,基本不用!
主要有如下几个原因:
  1. Mysql内存临时表不支持TEXT、BLOB这样的大数据类型,如果查询中包含这样的数据,查询效率会非常慢。
  2. 数据库特别大,内存占用高,维护也比较麻烦。
  3. binlog太大,如果是主从同步的架构,会导致主从同步效率问题!
因此,不推荐使用blob等类型!

8:表中有大字段X(例如:text类型),且字段X不会经常更新,以读为主,那么是拆成子表好?还是放一起好?
其实各有利弊,拆开带来的问题:连接消耗;不拆可能带来的问题:查询性能,所以要看你的实际情况,如果表数据量比较大,最好还是拆开为好。这样查询速度更快。
9:字段为什么要定义为NOT NULL?
一般情况,都会设置一个默认值,不会出现字段里面有null,又有空的情况。主要有以下几个原因:
1. 索引性能不好,Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。
2. 如果某列存在null的情况,可能导致count() 等函数执行不对的情况。看一下2个图就明白了:


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







欢迎光临 教育改变生活 (http://bbs.goldoar.com/) Powered by Discuz! X3.2