mysql

mysql

  1. 一条SQL查询语句是如何执行的

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133210089.png" alt="image-20200406133210089" style="zoom:25%;" />

  2. binlog 和 redolog

    • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
    • redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
    • redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
  3. 两阶段提交

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133241695.png" alt="image-20200406133241695" style="zoom:25%;" />

  4. 事务的隔离级别

    • 读未提交:事务还没提交时,它做的变更就能被别的事务看到
    • 读提交:事务提交之后,它做的变更才会被其他事务看到
    • 可重复读:事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交变更对其他事务也是不可见的。
    • 串行化:顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
  5. B树和B+树区别

    • m阶的B树

      • 根结点至少有两个子女
      • 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
      • 每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
      • 所有的叶子结点都位于同一层
      • 每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。
    • m阶的B+树

      • 有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
      • 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
      • 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。
    • B+树的优势:

      • 单一节点存储更多的元素,使得查询的IO次数更少。
      • 所有查询都要查找到叶子节点,查询性能稳定。
      • 所有叶子节点形成有序链表,便于范围查询。
  6. 为什么B+控制高度

    • 磁盘读取依靠的是机械运动,一次磁盘IO的时间,大概9ms左右,是访问内存的十万倍左右;
    • 预读:每一次IO时,不仅仅把当前磁盘地址的数据加载到内存,同时也把相邻数据也加载到内存缓冲区中。因为局部预读原理说明:当访问一个地址数据的时候,与其相邻的数据很快也会被访问到。每次磁盘IO读取的数据我们称之为一页(page)。一页的大小与操作系统有关,一般为4k或者8k。这也就意味着读取一页内数据的时候,实际上发生了一次磁盘IO。
    • 数据库索引是存储在磁盘上,当表中的数据量比较大时,索引的大小也跟着增长,达到几个G甚至更多。当我们利用索引进行查询的时候,不可能把索引全部加载到内存中,只能逐一加载每个磁盘页,这里的磁盘页就对应索引树的节点。
    • 所以,减少磁盘IO的次数就必须要压缩树的高度,让瘦高的树尽量变成矮胖的树,在内存中完成中,不涉及到磁盘IO,耗时可以忽略不计。相同数量的key在B树中生成的节点要远远少于二叉树中的节点,相差的节点数量就等同于磁盘IO的次数。这样到达一定数量后,性能的差异就显现出来了。
  7. 聚簇索引和非聚簇索引

    • 主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引。
    • 非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引。基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。
  8. MySQL Hash 索引适用情况

    哈希索引基于哈希表实现,只有精确匹配索引的所有列的查询才有效。哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序。哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。

    哈希索引一般适用于:不需要做排序、范围查询的需求。只要是只需要做等值比较查询,而不包含排序或范围查询的需求,都适合使用哈希索引。

  9. MySQL 索引是不是越多越好?为什么?

    索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

  10. 联合索引是怎么加锁的?

    当使用多列唯一索引时,加锁需要明确要锁定的行(即加锁时使用索引的所有列),InnoDB才会认为该条记录为唯一值,锁才会降级为Record Lock。否则会使用Next-Key Lock算法,锁住范围内的数据。

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133323592.png" alt="image-20200406133323592" style="zoom:33%;" />

  11. 主键能不能太大,为什么,如果太大,底层数据结构会不会变化,为什么。

    主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。

    B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。如果所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。除了性能外,页分裂操作还影响数据页的利用率。

  12. 事务隔离的实现

    实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133406965.png" alt="image-20200406133406965" style="zoom:33%;" />

  13. 分别阐述在串行化隔离级别中,怎么加读锁和写锁,这里的锁是什么锁:表锁?行锁?还是其他锁?

  14. ACID实现原理

    • 事务的四个特性: ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)

    • 原子性:实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

    • 一致性:事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要代码层面进行保障。

    • 隔离性:

      • (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
      • (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性
    • 持久性:如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。

  15. 可重复读怎么实现的,怎么定位到哪一行

    InnoDB 在实现 MVCC 时用到的一致性读视图,用于支持读提交和可重复读隔离级别的实现。

    InnoDB 里面每个事务有一个唯一的事务 ID,叫作 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。而每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。也就是说,数据表中的一行记录,其实可能有多个版本 (row),每个版本有自己的 row trx_id。每次需要的时候根据当前版本和 undo log 计算出来的。

    在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图。

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133459120.png" alt="image-20200406133459120" style="zoom:33%;" />

  16. 幻读

    • 幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。
    • 锁只能锁住行,但是新插入记录这个动作,要更新的是记录之间的“间隙”。因此,为了解决幻读问题,InnoDB 只好引入新的锁,也就是间隙锁 (Gap Lock)。
  17. 死锁

    • 当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态。
    • 四个必要条件
      • 互斥条件:一个资源每次只能被一个进程使用。
      • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
      • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
      • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
    • 死锁的预防和避免方法:减少死锁的主要方向,就是控制访问相同资源的并发事务量。
      • 按同一顺序访问对象。
      • 避免事务中的用户交互。
      • 保持事务简短并在一个批处理中。
      • 使用低隔离级别。
      • 使用绑定连接。
  18. InnoDB下如何加锁?

    <img src="https://user-gold-cdn.xitu.io/2019/10/20/16de975b25048a19?imageslim" alt="img" style="zoom:60%;" />

    • 全局锁:Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表都 select 出来存成文本。

    • 表锁:一种是表锁,一种是元数据锁(meta data lock,MDL)。lock tables … read/write。可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。另一类表级的锁是 MDL(metadata lock)。MDL 不需要显式使用,在访问一个表的时候会被自动加上。

    • 行锁:

      排他锁:for update为所有查询select的记录加上拍他锁。锁的期间,不允许其他任何尝试获取锁(包括读锁和写锁)的请求,只有这个锁被释放掉才能被另外一个事务获取锁。

      共享锁:对select查询的所有记录加上共享锁(或者说获取这些记录的共享锁)。对另外一个获取“共享锁”的事务共享当前正在读的数据。但对写锁却是“排它”的,意思在获取的读锁的时候不允许写锁进行写数据,要不然就会出现脏读(读到的数据因为被更改而过时)。

  19. 分析delete from table where user_id=“1”这句话怎么加锁的?

    • 非唯一索引进行删除的时候,锁情况为:4 lock struct(s):4种锁结构,分别为IX,idx_c1的next key 锁(3,5] ,主键的行锁,还有idx_c1的gap锁(5,7);3 row lock(s):除去IX的都是算在row lock里面。

    • 根据唯一索引进行删除的时候,锁情况为:3 lock struct(s):3种锁结构,分别为IX,idx_c1和主键的行锁,没有gap锁;2 row lock(s):除去IX的都是算在row lock里面,没有gap,因此为2个。

  20. 乐观锁、悲观锁定义和使用场景

    • 定义

    悲观锁(Pessimistic Lock): 每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁。由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待。

    乐观锁(Optimistic Lock): 每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。

    • 使用场景

    悲观锁比较适合强一致性的场景,但效率比较低,特别是读的并发低。乐观锁则适用于读多写少,并发冲突少的场景。

  21. 存储引擎的索引结构

    • myisam:MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址,叫做非聚集索引。
    • innodb:把数据放在主键索引上,其他索引上保存的是主键 id。这种方式,我们称之为索引组织表(Index Organizied Table)。
    • memory:Memory 引擎的数据和索引是分开的,把数据单独存放,索引上保存数据位置的数据组织形式,我们称之为堆组织表。
  22. Innodb 和MyISAM区别

    • InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。
    • MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。如果数据表主要用来插入和查询记录,则MyISAM引擎能提供较高的处理效率
    • MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎作为临时表,存放查询的中间结果
    • MyISAM 这种存储引擎不支持事务,不支持行级锁,只支持并发插入的表锁,主要用于高负载的select。MyISAM的优势在于占用空间小,处理速度快。缺点是不支持事务的完整性和并发性。
  23. 深度分页

    • 以结果作为条件,已查询条件的变化换取分页的不变。 分页查询我们一般都是逐渐往后翻页的,那么我们可以很清晰的知道,在当前查询页的最后一条数据的时间点,那么,以此时间点再查询20条,那么 我们当前的页数就同样还是0,以时间点的推移换取页数的不变,减少其偏移量的计算。
    • 采用子查询模式,其原理依赖于覆盖索引,当查询的列,均是索引字段时,性能较快,因为其只用遍历索引本身。我们自己创建的非主键索引,都是非聚集索引,其不包含非索引字段,所以数据结构较小,系统能快速遍历。我们知道索引时b+树结构,系统能很容易的知道866613,位于索引树的位置。
    • 复合索引:其原理同样是索引覆盖的思想,只不过是其以查询条件的一份作为索引,最终的索引字段是主键id。这种场景严格依赖于索引的顺序。查询的结果也不能包含非索引字段,需再走一次子查询。
  24. binlog写入机制

    事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。

  25. 主备流程

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133546497.png" alt="image-20200406133546497" style="zoom:33%;" />

    主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写 binlog。备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。

    • 在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。
    • 在备库 B 上执行 start slave 命令,这时候备库会启动两个线程,就是图中的 io_thread 和 sql_thread。其中 io_thread 负责与主库建立连接。
    • 主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog,发给 B。
    • 备库 B 拿到 binlog 后,写到本地文件,称为中转日志(relay log)。
    • sql_thread 读取中转日志,解析出日志里的命令,并执行。
  26. 分库分表后怎么保证主键仍然是递增的?

    • 数据库自增 id

    • 设置数据库 sequence 或者表自增字段步长:可以通过设置数据库 sequence 或者表的自增字段步长来进行水平伸缩。将来如果还要增加服务节点,就不好搞了。

    • UUID:好处就是本地生成,不要基于数据库来了;不好之处就是,UUID 太长了、占用空间大,作为主键性能太差了;更重要的是,UUID 不具有有序性,会导致 B+ 树索引在写的时候有过多的随机写操作。如果你是要随机生成个什么文件名、编号之类的,你可以用 UUID,但是作为主键是不能用 UUID 的。

    • 获取系统当前时间:这个就是获取当前时间即可,但是问题是,并发很高的时候,比如一秒并发几千,会有重复的情况。

    • snowflake 算法:开源的分布式 id 生成算法,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。

  27. 均摊扩容

    主从:一个Master数据库,多个Salve,然后利用MySQL的异步复制能力实现读写分离

    数据切分:一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分;另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

    分库分表分区

Mycat:分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信。其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。


Cobar:数据迁移不是以数据为单位,而是以schema为单位,迁移过程中使用Mysql的同步机制。
  1. CAP:一个提供数据服务的存储系统无法同时满足数据一致性(consistency)、数据可用性(Availibility)、分区耐受性(Partition Tolerance 系统具有网络分区的伸缩性)

  2. 如何分析“慢查询”日志进行 SQL/索引 优化?

    • 慢查询日志开启:
    // 1. 在配置文件my.cnf或my.ini中在[mysqld]一行下面加入两个配置参数
    
    log-slow-queries=/data/mysqldata/slow-query.log
    
    long_query_time=2
    
    // 2. mysqldumpslow
    /path/mysqldumpslow -s c -t 10 /database/mysql/slow-query.log       
    
    • explain分析查询

    使用 EXPLAIN 关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。通过explain命令可以得到:

    possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

    key:实际使用的索引。如果为NULL,则没有使用索引。MYSQL很少会选择优化不足的索引,此时可以在SELECT语句中使用USE INDEX(index)来强制使用一个索引或者用IGNORE INDEX(index)来强制忽略索引

    key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好

    ref:显示索引的哪一列被使用了,如果可能的话,是一个常数

    type:显示查询使用了何种类型。从最好到最差的连接类型为system、const、eq_reg、ref、range、index和ALL

    a. ALL: MySQL进行全表扫描。

    b. index:全索引扫描。index与ALL区别为index类型只遍历索引树

    c. range:只检索给定范围的行,使用一个索引来选择行

    d. ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

    e. eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

    f. const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system

  3. 建索引sql

    ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)
    
  4. 假如查询 A in (), MySQL 是针对 N 个值分别查一次索引, 还是有更好的操作?

    left join
    
  5. 瞬时写入量很大可能会打挂存储, 怎么保护?

    断路器有三种状态:关闭、开放、半开放。

    • 最开始处于关闭状态,一旦检测到错误到达一定阈值,便转为开放状;
    • 这时候会有个 reset timeout,即开始准备恢复了,转移到半开放状态;
    • 尝试放行一部分请求到后端,一旦检测成功便回归到关闭状态,即恢复服务;
  6. mysql join的底层原理

    • Index Nested-Loop Join

    先遍历表 t1,然后根据从表 t1 中取出的每行数据中的 a 值,去表 t2 中查找满足条件的记录。在形式上,这个过程就跟我们写程序时的嵌套查询类似,并且可以用上被驱动表的索引,所以我们称之为“Index Nested-Loop Join”,简称 NLJ。

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133643393.png" alt="image-20200406133643393" style="zoom:40%;" />

    • Simple Nested-Loop Join

    表 t2 的字段 b 上没有索引,因此再用图 2 的执行流程时,每次到 t2 去匹配的时候,就要做一次全表扫描。

    • Block Nested-Loop Join

    把表 t1 的数据读入线程内存 join_buffer 中,由于我们这个语句中写的是 select *,因此是把整个表 t1 放入了内存;扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。

    从时间复杂度上来说,这两个算法是一样的。但是,Block Nested-Loop Join 算法的这 10 万次判断是内存操作,速度上会快很多,性能也更好。

    <img src="/Users/anyao/Library/Application Support/typora-user-images/image-20200406133722327.png" alt="image-20200406133722327" style="zoom:40%;" />

  7. mongo优点?

    文档模型更自然:与关系型数据库中表结构不同,文档中可以嵌入数组和子文档,就像程序中的数组和成员变量一样。
    性能:三范式所带来的性能损失也是一个问题。为了满足一个查询,多个表的数据都要参与 Join,每一个表都对应着磁盘的一次读取。
    灵活:没有 Schema(模式、数据模型),就不需要改动数据库,只需要在应用层做必要的改动。
    可扩展性:通过自带的Mongos集群,只需要在适当的时候继续添加Mongo分片,就可以实现程序段自动水平扩展和路由,一方面缓解单个节点的读写压力,另外一方面可有效地均衡磁盘容量的使用情况。

  8. Mongo和mysql比较大的区别,为啥有人用mysql不用mongo?

    • B树:

      • 树内的每个节点都存储数据
      • 叶子节点之间无指针相邻
    • B+树:

      • 数据只出现在叶子节点
      • 所有叶子节点增加了一个链指针

    B树的树内存储数据,因此查询单条数据的时候,B树的查询效率不固定,最好的情况是O(1)。我们可以认为在做单一数据查询的时候,使用B树平均性能更好。但是,由于B树中各节点之间没有指针相邻,因此B树不适合做一些数据遍历操作。

    B+树的数据只出现在叶子节点上,因此在查询单条数据的时候,查询速度非常稳定。因此,在做单一数据的查询上,其平均性能并不如B树。但是,B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。

    Mysql中数据遍历操作比较多,所以用B+树作为索引结构。而Mongodb是做单一查询比较多,数据遍历操作比较少,所以用B树作为索引结构。

    • 那么为什么Mysql做数据遍历操作多?而Mongodb做数据遍历操作少呢?

    因为Mysql是关系型数据库,而Mongodb是非关系型数据。由于关系型数据库和非关系型数据的设计方式上的不同。导致在关系型数据中,遍历操作比较常见,因此采用B+树作为索引,比较合适。而在非关系型数据库中,单一查询比较常见,因此采用B树作为索引,比较合适。

  9. mongodb底层原理或者数据结构是什么,事务处理,插入和mysql有什么区别,为什么会慢

  • 底层原理或者数据结构

    MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)。总体来说,Mysql选用B+树和MongoDB选用B-树还是以自己的需求来选择的。

  • 插入速度慢

    B树每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。由于B+Tree内节点去掉了data域,因此可以拥有更大的出度,容纳更多的节点,能够有效减少磁盘IO次数。

  • 事务

    <img src="http://www.ywnds.com/wp-content/uploads/2016/09/201609141101047.png" alt="img" style="zoom: 60%;" />

  1. 如何进行数据库优化的?

    • 优化sql和索引

      (1) 用慢查询日志定位执行效率低的SQL语句

      (2) 用explain分析SQL的执行计划

      (3) 确定问题,采取相应的优化措施,建立索引啊,等

    • 搭建缓存:将复杂的、耗时的、不常变的执行结果缓存起来,降低数据库的资源消耗。搭建缓存后,系统的复杂性增加了。你需要考虑很多问题,比如:缓存和数据库一致性问题?缓存击穿、缓存穿透、缓存雪崩问题如何解决?是否有做缓存预热的必要。

    • 读写分离:在应用层,区分读写请求。或者利用现成的中间件mycat或者altas等做读写分离。

      需要注意的是,只要你敢说你用了主从架构,有三个问题,你要准备:

      (1)主从的好处:实现数据库备份,实现数据库负载均衡,提告数据库可用性。

      (2)主从的原理:主库有一个log dump线程,将binlog传给从库。从库有两个线程,一个I/O线程,一个SQL线程,I/O线程读取主库传过来的binlog内容并写入到relay log,SQL线程从relay log里面读取内容,写入从库的数据库。

      <img src="https://www.cnblogs.com/images/cnblogs_com/rjzheng/1281019/o_youhua1.jpg" alt="image" style="zoom:80%;" />

      (3)如何解决主从一致性:我不建议在数据库层面解决该问题。根据CAP定理,主从架构本来就是一种高可用架构,是无法满足一致性的哪怕你采用同步复制模式或者半同步复制模式,都是弱一致性,并不是强一致性。所以,推荐还是利用缓存,来解决该问题。

      步骤如下:

      1、自己通过测试,计算主从延迟时间,建议mysql版本为5.7以后,因为mysql自5.7开始,多线程复制功能比较完善,一般能保证延迟在1s内。不过话说回来,mysql现在都出到8.x了,还有人用5.x的版本么。

      2、数据库的写操作,先写数据库,再写cache,但是有效期很短,就比主从延时的时间稍微长一点。

      3、读请求的时候,先读缓存,缓存不存在(这时主从同步已经完成),再读数据库。

    • 利用分区表:所有数据还在一个表中,但物理存储根据一定的规则放在不同的文件中。这个是mysql支持的功能,业务代码不需要改动,但是sql语句需要改动,sql条件需要带上分区的列。

      缺点:

      (1)分区键设计不太灵活,如果不走分区键,很容易出现全表锁

      (2)在分区表使用ALTER TABLE … ORDER BY,只能在每个分区内进行order by。

      (3)分区表的分区键创建索引,那么这个索引也将被分区。分区键没有全局索引一说。

      (4)自己分库分表,自己掌控业务场景与访问模式,可控。分区表,研发写了一个sql,都不确定该去哪个分区查,不太可控。

    • 垂直拆分:垂直拆分的复杂度还是比水平拆分小的。将你的表,按模块拆分为不同的小表。拆分原则一般是如下三点:

      (1)把不常用的字段单独放在一张表。

      (2)把常用的字段单独放一张表

      (3)经常组合查询的列放在一张表中(联合索引)。

    • 水平拆分:水平拆分模块间耦合性太强,成本太大,不是特别推荐。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容