软件测试面试题_常见数据问题总结

数据库

图片[1]-软件测试面试题_常见数据问题总结-软件测试圈

关系型数据库和非关系型数据库的区别是什么

自己了解过的关系型数据库:mysql sqlserve oracle

非关系型数据库:mongodb redis(nodejs爬书籍)

关系型优点:

  • 查询能力高
  • 一致性高(锁机制)
  • 表具有逻辑性,易于理解

关系型缺点:

  • 不适用高并发读写
  • 不适用海量数据高效读写
  • 层次多,扩展性低
  • 维护一致性开销大
  • 涉及联表查询,复杂,慢

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等

优点:

  • 由于数据之间没有关联关系,所以易扩展,也易于查询。

  • 数据结构灵活,每个数据都可以有不同的结构。

  • 由于降低了一致性的要求,所以查询速度更快。

缺点:

  • 不提供SQL支持,每种NoSQL数据库都有自己的一套增删改查方式,学习成本较高
  • 数据之间没有关联性,不易于理解
  • 对于对事务性系统的处理上,没有优势

MyISAM和InnoDB的区别是什么(抽象)

  1. 存储结构
  • MyISAM:每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。

  • InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小。

  1. 存储空间
  • MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。

  • InnoDB:需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。

  1. 可移植性、备份及恢复
  • MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。

  • InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。

  1. 事务支持
  • MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。

  • InnoDB:提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。

  1. AUTO_INCREMENT
  • MyISAM:可以和其他字段一起建立联合索引。引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。

  • InnoDB:InnoDB中必须包含只有该字段的索引。引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。

  1. 表锁差异
  • MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。

  • InnoDB:支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

  1. 全文索引
  • MyISAM:支持 FULLTEXT类型的全文索引

  • InnoDB:不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。

  1. 表主键
  • MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。

  • InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。

  1. 表的具体行数
  • MyISAM:保存有表的总行数,如果select count(*) from table;会直接取出出该值。

  • InnoDB:没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。

  1. CURD操作
  • MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。

  • InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。

  1. 外键
  • MyISAM:不支持

  • InnoDB:支持

  • 《MySQL高性能》上面有一句话这样写到:

不要轻易相信“MyISAM比InnoDB快”之类的经验之谈,这个结论往往不是绝对的。在很多我们已知场景中,InnoDB的速度都可以让MyISAM望尘莫及,尤其是用到了聚簇索引,或者需要访问的数据都可以放入内存的应用。

简要谈谈MySQL索引的原理

利用MySQL的索引最主要的用途是:提高查询效率。

MySQL索引使用的数据结构主要有 BTree索引 和 哈希索引 。

对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。

MySQL的BTree索引使用的是B树中的B+Tree,但对于主要的两种存储引擎的实现方式是不同的。

  • MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
  • InnoDB: 其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”。而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

并不是说索引建的越多越好,创建索引也是有代价的:

  1. 索引需要占用硬盘空间,所以,当查询数据时,索引又可以看作是拿空间换时间的操作。
  2. 如果要插入新的数据,就需要重新建立索引,需要花费一定的时间。

在什么情况下,MySQL的索引会失效

  • 不满足最左前缀法则:在进行复合索引查询时,索引从最左侧开始,不跳过其他索引查询,则索引有效;如果跳过则索引无效。
  • 范围查询右侧列索引失效
  • 查询字符串类型的字段不带单引号索引失效:如果 id 是 varchar 类型,且是主键索引,但是查询时不带' '号,则索引失效
  • mysql在使用like查询中,使用不当

MySQL的三大范式

三大范式的目的:建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。

  1. 第一范式 (1NF)【字段不可再分】
    每一列属性都是不可再分的属性值,确保每一列的原子性
    两列的属性相近或相似或一样,尽量合并属性一样的,确保不产生冗余数据。
    比如:“地址” 仍可以拆分成 “省”、“市”、“区县”、“详细地址”。
  2. 第二范式 (2NF)【每一行数据只做一件事】
    每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
    比如:商家表中,若维护门店ID、门店名称、门店地址,就不符合第二范式,应该专门拆分出门店表。
  3. 第三范式 (3NF) 【每个属性都和主键有直接关系】
    数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。
    比如,学生表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)就不满足第三范式,应该拆分成:学生表(学号,姓名,年龄,性别,所在院校)和 院校表(院校,院校地址,院校电话)。

MySQL事务的四大特性分别是什么

  • 原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  • 一致性(Consistency): 执行事务后,数据库从一个正确的状态变化到另一个正确的状态;
  • 隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  • 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

什么是脏读、幻读和不可重复读

脏读

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。(未提交 读)

不可重复读

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,(不可重复读)

幻读

是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有 没有修改的 数据行,就好象 发生了幻觉一样。

如何避免脏读、不可重复读、幻读?

隔离级别设置为:可串行化(Serializable)锁表

事务隔离级别有哪些?

事务隔离级别有:读未提交、读已提交、可重复读和可串行化。

对MySQL的慢查询了解么?请简单讲讲

慢查询,顾名思义,执行很慢的查询。一般指超过 long_query_time 参数设定的时间阈值(默认10s),就被认为是慢的,是需要优化的。慢查询被记录在慢查询日志里。
慢查询日志默认是不开启的,需要手动来设置这个参数。如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。
慢查询日志支持将日志记录写入文件和数据库表。

分库分表的好处是什么?谈谈你对分库分表的了

当业务发展到一定阶段时,可能会出现以下情形:

  • 数据库的有状态性,不那么容易扩展
  • 海量数据和高并发业务下的单机限制,如存储容量、连接数、单机读/写处理能力等
  • DBA规范性要求,单表限制1kw行以内

这个时候,就需要进行分库分表,来提升查询性能。

什么是内连接、左连接、右连接、外连接和全连接查询

全连接mysql没有这个语法

互联网应用的缓存数据处理流程是怎样的?为什么要用缓存

  1. 如果用户请求的数据在缓存中就直接返回。
  2. 缓存中不存在的话就看数据库中是否存在。
  3. 数据库中存在的话就更新缓存中的数据。
  4. 数据库中也不存在的话就返回空数据。

缓存的作用:

使用缓存,主要是为了提升用户体验以及应对更多的用户,即缓存可以提升“高并发”和“高性能”。

谈谈Redis常见的数据结构,并分别简述不同数据结构的使用场景

  • string:key-value模型,保存文本和二进制数据,计数的场景(点赞转发数量)
  • list:双向链表(反向查找和遍历,负担也大了),发布订阅或者消息队列慢查询用到
  • hash:string类型的field和value的映射表(适合存储对象)
  • set:无序集合(不希望重复数据,提供list没有的是否存在成员接口),场景(交并差集操作)
  • sorted set:相比set多了权重参数(score),借此有序排序,范围获取元素

什么是缓存穿透、缓存击穿和缓存雪崩

缓存穿透:高并发查询不存在的数据,缓存不命中,就给数据库造成压力,解决方法

  • 缓存无效key(设置过期时间)
  • 使用布隆过滤器

缓存击穿:高并发查询过期数据(比如活动),缓存不命中,查询落在数据库上

缓存雪崩:高并发大量缓存key同一时间失效,请求落在数据库上

常见解决方案:

针对 Redis 服务不可用的情况:

  • 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
  • 限流,避免同时处理大量的请求。

针对热点缓存失效的情况:

  • 设置不同的失效时间比如随机设置缓存的失效时间。
  • 缓存永不失效。

如何保证数据库和缓存双写时数据一致性

常规做法是引入旁路缓存模式( Cache Aside Pattern),也就是:读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应;更新的时候,先删除缓存,然后再更新数据库

关于更新缓存,有两个细节值得注意:

  1. 更新数据的时候,应该先操作数据库,还是先操作缓存?

如果先操作数据库,再删除缓存,假如这个时候,两个动作的原子性被破坏,数据库是新数据,但缓存中是旧数据,接下来前端对缓存进行访问,返回给前端的依然是旧数据,造成数据不一致,在业务上无法接受。

如果先删除缓存,再操作数据库,假如数据库数据更新失败,此时缓存是空的,数据库还是旧数据,接下来前端对缓存进行访问,缓存找不到,会请求数据库,至少这时数据的一致性还是可以保证的。

  1. 更新数据的时候,应该删除缓存还是更新缓存?

有时候,缓存的数据不是简简单单的直接从数据库取出的值,而是经过从数据库中获取数据并计算之后才写入到缓存中,此时更新缓存的代价是比更新数据库要大的。

另外,删除缓存,而不是更新缓存,就是一个lazy计算的思想。不要每次都重新做复杂的计算,不管它会不会用到,而是让它到需要被使用的时候再重新计算。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
相关推荐
  • 暂无相关文章
  • 评论 抢沙发

    请登录后发表评论