MySql 在面试的时候也是一道必不可缺的门槛,面试的时候面试官经常也会考验你数据库方面的能力,例如优化性能,大数据量怎么处理等。这边我整理几个经常可能会问到的几个问题。
具体可能会有以下几个问题:
1:为什么要设定一个主键?
2:项目中是使用自增主键还是使用UUID?
3:主键为什么不推荐涉及到业务含义?
4:表示枚举的字段为什么不用enum类型?
5:货币字段用什么类型?
6:时间字段用什么类型?
7:为什么不直接存储照片,视频,音频等这些内容数据?
8:有些字段为什么要设置成NOT NULL?
大概是上面8个问题,我这里所答的答案并非标准答案,供大家参考,不对的可以私信我。这里我是基于innodb的引擎的,我使用这个引擎比较多,还有其他的引擎,大家可以搜索理解下。各有各的好处,看业务的需要选择适合的引擎模式。
下面进入正文:
问题1:为什么要设定一个主键?
答:因为你不设定 一个主键,innodb也会在底层给你设定一个隐藏的自增列主键,这样的话,还不如自己指定一个主键。大多数情况使用主键可以大大提升查询的效率。外拓展(explain +SQL语句,可以知道不使用索引跟使用索引的效率,range级别都需要优化!)。
问题2:主键是使用自增的还是使用UUID?
答:各有利有弊,需要效率更高的使用自增主键,innodb会维护主键是一个聚集索引,如果主键是自增的,则每次插入新的数据时,会按照当前的顺序进行插入,如果达到一定的页节点值,则会新开一个页存储数据。如果不是自增的UUID,则插入的时候可能会在数据列中间插入数据,这期间可能引发数据库自己维护排序,还有会引发页分裂,会造成表碎片,到时数据量很大的情况,可能会不得力重构表结构!(可以查询UUID与自增主键的区别)
问题3:主键为什么不推荐涉及到业务含义?
答:因为任何跟业务有关系的数据列,都有发生改变的可能性!大多数情况下业务复杂都会变的。主键一旦带上业务意义,那么主键就可能发生改变,一发生改变那么数据在磁盘存储的位置也可能发生改变,就有可能造成页分裂,产生表碎片!
还有,如果带有业务含义的,顺序就不一定是自增的了。就会导致数据的插入顺序,并不能保证后面插入的数据主键,一定比前面的大,如果出现了,后面的主键比前面的小。就可能产生页分裂,产生表碎片。
问题4:表示枚举的字段为什么不用enum类型?
答:工作中表示枚举的字段,一般都用tinyint类型。为什么不用enum类型的呢?有2个原因,
(1)EUNM类型的在排序操作 ORDER BY 时,效率低下,需要额外的操作。
(2)如果枚举的数据是数值,就会有陷阱。
比如,创建一个表
Create Table test (foobar EUNM('0','1','2'));
此时,如果你执行插入
insert into test values (1);
你会发现插入的结果为
产生一个错误的结果!正确的插入应该是下面
INSERT INTO test VALUES (`1`);
问题5:货币字段用什么类型?
答:如果货币单位是分,可以用Int 类型。如果坚持用元的话,就用Decimal。一定不要说用float跟double!因为这两个类型在插入数据的时候会损失精度的!这两个是以二进制的方式进行存储的,所以有一定误差。加入你插入 一个数据为1234567.23,你会发现数据变了1234567.25。这个具体你们可以在数据库操作试试
问题6:时间字段用什么类型?
答:这个没有固定的答案,可以根据业务的实际来谈论,可以使用varchar 也可以使用datetime,也可以用timestamp。
(1)varchar类型存储,优点在于很直观,但是也有坑的情况,当出现多个数值一样的情况下,可能就分不清时间了,比如2019111。你说我是2019的1月11号呢还是2019年的11月1号?使用字符类型的,底层是不会给你做检验的。如果做时间比较运算,就需要用到SET_TO_DATE等一些时间函数,然后会发现这样写,可能无法命中索引。数据量一大你就会发现是个坑!
(2)datetime类型,占用8个字节,他存储的时间范围是1000-01-01-----9999-12-31:00:00:00,他存的范围很大,不好的地方在于他存储的时间是绝对值,是不会带有时区的信息的,如果改变了数据库的时区,这个保存的时间也是不会发生变化的!
(3)timestamp类型,占用4个字节,这个类型是带有时区信息的,如果系统改变了时区,那存储这个字段的列自己也会自动发生改变。这个特性是用来做一些国际化的项目,但是时间范围比datetime小很多,1970-01-01------2038-01-19,超过这范围是无法存储的
问题7:为什么不直接存储照片,视频,音频等这些内容数据?
答:在实际项目中,我们一般都是只存数据的文件路径的。MySql 是有字段可以存储这些数据的,text跟blob类型,但是我生产中一般不会用的。
(1)做数据同步的时候,例如我们的主从,是根据binlog日志来进行。如果binlog内容太多的话,会导致主从同步很慢!就可能引发一些其他的问题!
(2)Mysql 内存临时表操作 不支持这2个类型的,如果查询的时候出现这两个类型的数据,在排序的时候,就不能使用内存临时表了,就要是磁盘内存来操作,会查询的很慢!(具体可以查mysql底层排序机制)
问题8:有些字段为什么要设置成NOT NULL?
答:有NULL的话影响索引的性能
(2)查询会出现一些不可预料的结果
例如你在求数据条数时,count('列名') 你会发现null值的没有统计进去,(具体可以查询操作一下)