数据存储和消息队列

二、数据存储和消息队列

2.1、数据库

  • MySQL 索引使用的注意事项(点击打开链接)

  • 1.WHERE字句的查询条件里有 NOT IN 、<>、!=,MYSQL将无法使用索引;

    2.WHERE字句的查询条件里使用了函数,MYSQL将无法使用索引

    3.在JOIN操作中,MYSQL只有在主键和外键的数据类型相同时才能使用索引,否则即使建立了索引也不会使用

    4.使用了比较操作符LIKE和REGEXP,MYSQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是LIKE 'abc%',MYSQL将使用索引;如果条件是LIKE '%abc'或者'_abc%',MYSQL将不使用索引。

    5.在ORDER BY操作中,MYSQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。尽管如此,在涉及多个数据表的查询里,即使有索引可用,那些索引在加快ORDER BY操作方面也没什么作用。

    使用order by特别提示:
    1>mysql一次查询只能使用一个索引。如果要对多个字段使用索引,建立复合索引。
    2>在ORDER BY操作中,MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。

    6.如果某个数据列里包含着许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含了净是些诸如“0/1”或“Y/N”等值,就没有必要为它创建一个索引。

    7.使用短索引: 对串列进行索引,如果可以就应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。(针对hash的索引方式,对每个值都做hash值存储I/O操作存储索引信息)

    8.如果条件中有or(并且其中有or的条件是不带索引的),即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)。注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

    9.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

    10.对于那些定义为text、image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。

    11.只要列中包含有NULL值,都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此符合索引就是无效的。

    12.组合索引之最左前缀:顾名思义,就是最左优先,上例中我们创建了name_age_course多列索引,相当于创建了(name)单列索引,(name,age)组合索引以及(name,age,course)组合索引。在单独使用(age)、(age,course)等条件下索引无效


  • DDL、DML、DCL分别指什么

  • DML(data manipulation language): 
    它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言 
    DDL(data definition language): 
    DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用 
    DCL(Data Control Language): 
    是数据库控制功能。是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL

  • explain命令

  • 在工作中,我们用于捕捉性能问题最常用的就是打开慢查询,定位执行效率差的SQL,那么当我们定位到一个SQL以后还不算完事,我们还需要知道该SQL的执行计划,比如是全表扫描,还是索引扫描,这些都需要通过EXPLAIN去完成。EXPLAIN命令是查看优化器如何决定执行查询的主要方法。可以帮助我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。需要注意的是,生成的QEP并不确定,它可能会根据很多因素发生改变。MySQL不会将一个QEP和某个给定查询绑定,QEP将由SQL语句每次执行时的实际情况确定,即便使用存储过程也是如此。尽管在存储过程中SQL语句都是预先解析过的,但QEP仍然会在每次调用存储过程的时候才被确定。

  • left join,right join,inner join(点击打开链接)

  • 数据库事物ACID(原子性、一致性、隔离性、持久性)(点击打开链接)

  • 事物的隔离级别(读未提交、读以提交、可重复读、可序列化读)(点击打开链接)

  • 1、TransactionDefinition接口中定义五个隔离级别(isolation):

  • 脏读、幻读、不可重复读

  •  脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
     不可重复读:在同一事务中,多次读取到同一数据的结果有所不同。也就是说,后续读取可以读到另一个事务已经提交的更新数据。
     幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了,再查询的时候,第一个事务就会发现有些原来没有的记录。

  • 数据库的几大范式(点击打开链接)

  • 第一范式(1NF): 强调的是列的原子性,即列不能够再分成其他几列。(属性存在子集)

    第二范式(2NF): 首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。 

     第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 依赖于非主键列                               B,非主键列 依赖于主键的情况。A->B  C->A这里得出结论C->B就是传递依赖,箭头理解:B依赖A

  • 数据库常见的命令

  • 说说分库与分表设计(点击打开链接)

  • 分库与分表带来的分布式困境与应对之策(如何解决分布式下的分库分表,全局表?)(点击打开链接)

  • 说说 SQL 优化之道(点击打开链接)

  • *当只要一行数据时使用 LIMIT 1   **MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据

    *千万不要 ORDER BY RAND()

    *避免 SELECT * 

     *应尽量避免在 where 子句中对字段进行表达式操作

     *应尽量避免在where子句中对字段进行函数操作

     *很多时候用 exists 代替 in 是一个好的选择

     *应尽量避免在 where 子句中使用 != 或 <> 操作符

     *对于连续的数值,能用 between 就不要用 in 

     *应尽量避免在 where 子句中使用 or 来连接条件  **如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描

     *一般来说,预判一下过滤条件的范围。由于数据库是从后向前解析 SQL 语句的,通常建议把能过滤最多结果的条件放在后面,(不是一定的,mysql会根据索引做一些优化),尽量使过滤数据量大的条件先被执行

     *Join语句的优化   **尽可能减少Join语句中的NestedLoop的循环总次数;“永远用小结果集驱动大的结果集”

     *ORDER BY的实现与优化  **优化Query语句中的ORDER BY的时候,尽可能利用已有的索引来避免实际的排序计算(order字段尽量出现在条件中,并且有索引),可以很大幅度的提升ORDER BY操作的性能。

    *GROUP BY的实现与优化   **由于GROUP BY实际上也同样需要进行排序操作,而且与ORDER BY相比,GROUP BY主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在GROUP BY的实现过程中,与ORDER BY一样也可以利用到索引。

  • MySQL遇到的死锁问题、如何排查与解决(点击打开链接)

  • 存储引擎的 InnoDB与MyISAM区别,优缺点,使用场景

  • 主要区别:

    • 1).MyISAM是非事务安全型的,而InnoDB是事务安全型的。
    • 2).MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
    • 3).MyISAM支持全文类型索引,而InnoDB不支持全文索引。
    • 4).MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
    • 5).MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。
    • 6).InnoDB表比MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(alter table tablename type=innodb)。
    应用场景:
    • 1).MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
    • 2).InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。
  • 索引类别(B+树索引、全文索引、哈希索引)、索引的原理

  • 什么是自适应哈希索引(AHI)

  • 为什么要用 B+tree作为MySQL索引的数据结构

  • 聚集索引与非聚集索引的区别(点击打开链接)

根本区别

    聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

聚集索引

    聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。

非聚集索引

    非聚集索引制定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致,两种索引都采用B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,不会造成数据重排。

例子对比两种索引

    聚集索引就类似新华字典中的拼音排序索引,都是按顺序进行,例如找到字典中的“爱”,就里面顺序执行找到“癌”。而非聚集索引则类似于笔画排序,索引顺序和物理顺序并不是按顺序存放的。

  • 遇到过索引失效的情况没,什么时候可能会出现,如何解决

    1. 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)

      注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

      2.对于多列索引,不是使用的第一部分,则不会使用索引

      3.like查询是以%开头(以%结尾是可以的)

      4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

      5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引

  • limit 20000 加载很慢怎么解决(点击打开链接

  • 如何选择合适的分布式主键方案(点击打开链接)

  • 选择合适的数据存储方案

  • 常见的几种分布式ID的设计方案(点击打开链接)

    • 1. UUID

      UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符,UUID是16字节128位长的数字,通常以36字节的字符串表示,比如:3F2504E0-4F89-11D3-9A0C-0305E82C3301。

      UUID经由一定的算法机器生成,为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的复杂特性在保证了其唯一性的同时,意味着只能由计算机生成。

      优点:
      • 本地生成ID,不需要进行远程调用,时延低,性能高。
      缺点:
      • UUID过长,16字节128位,通常以36长度的字符串表示,很多场景不适用,比如用UUID做数据库索引字段。
      • 没有排序,无法保证趋势递增。
    • 2. Flicker方案

      这个方案是由Flickr团队提出,主要思路采用了MySQL自增长ID的机制(auto_increment + replace into)

    • 优点:
      • 充分借助数据库的自增ID机制,可靠性高,生成有序的ID。
      缺点:
      • ID生成性能依赖单台数据库读写性能。
      • 依赖数据库,当数据库异常时整个系统不可用。

  • 常见的数据库优化方案,在你的项目中数据库如何进行优化的(点击打开链接)

2.2、Redis

  • Redis 有哪些数据类型,可参考《Redis常见的5种不同的数据类型详解》String list set sortset hash(点击打开链接)

  • Redis 内部结构(点击打开链接

  • Redis 使用场景(点击打开链接

  • Redis 持久化机制,可参考《使用快照和AOF将Redis数据持久化到硬盘中

  • Redis 集群方案与实现

  • Redis 为什么是单线程的?(点击打开链接

  • redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销

  • 总体来说快速的原因如下:

    1)绝大部分请求是纯粹的内存操作(非常快速)

    2)采用单线程,避免了不必要的上下文切换和竞争条件

    3)非阻塞IO

  • 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级(点击打开链接

  • 使用缓存的合理性问题(点击打开链接

  • Redis常见的回收策略

  • redis 提供 6种数据淘汰策略:

    1. voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
    2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
    3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
    4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
    5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
    6. no-enviction(驱逐):禁止驱逐数据

2.3、消息队列

  • 消息队列的使用场景(点击打开链接)(点击打开链接

  • 消息的重发补偿解决思路

  • 1. 处理失败 指的是MessageListener的onMessage方法里抛出RuntimeException。

    2. Message头里有两个相关字段:Redelivered默认为false,redeliveryCounter默认为0。

    3. 消息先由broker发送给consumer,consumer调用listener,如果处理失败,本地redeliveryCounter++,给broker一个特定应答,broker端的message里redeliveryCounter++,延迟一点时间继续调用,默认1s。超过6次,则给broker另一个特定应答,broker就直接发送消息到DLQ。

    4. 如果失败2次,consumer重启,则broker再推过来的消息里,redeliveryCounter=2,本地只能再重试4次即会进入DLQ。

    5. 重试的特定应答发送到broker,broker即会在内存将消息的redelivered设置为true,redeliveryCounter++,但是这两个字段都没有持久化,即没有修改存储中的消息记录。所以broker重启时这两个字段会被重置为默认值

  • 消息的幂等性解决思路

  • 消息的堆积解决思路

  • 自己如何实现消息队列

  • 如何保证消息的有序性(点击打开链接


  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值