数据库相关知识

Posted by Qz on September 10, 2023

“Yeah It’s on. ”

基础

id

最常见的两种主键类型是自增Id和UUID,在比较这两种ID之前首先要搞明白一个问题,就是为什么主键有序比无序查询效率要快,因为自增Id和UUID之间最大的不同点就在于有序性。

我们都知道,当我们定义了主键时,数据库会选择表的主键作为聚集索引(B+Tree),mysql 在底层是以数据页为单位来存储数据的。

也就是说如果主键为自增 id的话,mysql 在写满一个数据页的时候,直接申请另一个新数据页接着写就可以了。如果一个数据页存满了,mysql 就会去申请一个新的数据页来存储数据。如果主键是UUID,为了确保索引有序,mysql 就需要将每次插入的数据都放到合适的位置上。这就造成了页分裂,这个大量移动数据的过程是会严重影响插入效率的

一句话总结就是,InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的。


但是为什么很多情况又不用自增id作为主键呢?

  • 容易导致主键重复。比如导入旧数据时,线上又有新的数据新增,这时就有可能在导入时发生主键重复的异常。为了避免导入数据时出现主键重复的情况,要选择在应用停业后导入旧数据,导入完成后再启动应用。显然这样会造成不必要的麻烦。而UUID作为主键就不用担心这种情况。
  • 不利于数据库的扩展。当采用自增id时,分库分表也会有主键重复的问题。UUID则不用担心这种问题。

自增id会担心主键重复,UUID不能保证有序性,有没有一种ID既是有序的,又是唯一的呢?

当然有,就是雪花ID

布隆过滤器

布隆过滤器(Bloom Filter)

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

索引

深入浅出数据库索引原理

数据库中的索引用于加快数据的搜索和访问速度。索引是一种数据结构,它包含了数据库中一个或多个列的值的副本。通过创建索引,数据库可以更快地定位和检索特定的数据行,减少了扫描整个表的开销。

索引具有以下几个作用:

  1. 提高查询性能:在数据库中创建索引后,查询操作会更快速地定位到所需的数据,减少了扫描整个表的时间,提高了查询效率。
  2. 加速排序操作:当需要对数据库表进行排序时,使用索引可以使排序操作更快速、更高效。
  3. 加速连接操作:当进行连接操作时,索引可以加快表之间的关联并提高连接查询的性能。
  4. 保证数据的唯一性:数据库中的索引可以通过设置唯一性约束,保证特定列的数据在表中的唯一性。

尽管索引可以提高查询性能,但也会降低插入、更新和删除数据的性能,因为每次对表进行数据变化时都需要维护索引的结构。因此,在创建索引时需要权衡索引的数量和使用场景,以便在满足查询性能需求的同时,尽量减少对数据操作的影响。

底层原理

https://www.bilibili.com/video/BV1Wm4y147mS/?vd_source=957714309e011b6f1d04da825e0e5491

以主键作为B+树索引的键值而构建的B+树索引,我们称之为聚集索引

在B+树中,叶子节点存储整条记录的数据,这样的索引为聚集索引

非聚集索引(非聚簇索引):以主键以外的列值作为键值构建的B+树索引,我们称之为非聚集索引。非聚集索引与聚集索引的区别在于非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据我们还需要根据主键再去聚集索引中进行查找,这个再根据聚集索引查找数据的过程,我们称为回表

明白了聚集索引和非聚集索引的定义,我们应该明白这样一句话:数据即索引,索引即数据

B+树

innodb存储引擎中是B+树索引

一篇文章讲透MySQL为什么要用B+树实现索引

MySQL的索引主要以B+树为主


B树和B+树区别:

  1. 节点结构:B树中的每个节点都存储了键值和对应的数据,而B+树中的非叶子节点只存储键值,所有的数据都存储在叶子节点中。
  2. 叶子节点链接:B树中的叶子节点之间没有任何链接,而B+树中的叶子节点通过指针进行链接,形成一个有序链表,方便范围查询。
  3. 节点指针:B树中的非叶子节点存储了指向子节点的指针,而B+树中的非叶子节点只存储了键值和对应的子节点的分界值,通过这个分界值来确定子节点的位置。
  4. 数据查询:在B树中,数据存储在各个节点,当查找时需要逐级查找,直到找到目标数据。而在B+树中,只需要在叶子节点上进行查找,大大减少了查找的时间。
  5. 范围查询:由于B+树中叶子节点之间有序链接,因此范围查询非常高效。而在B树中,由于节点之间没有链接,需要进行中序遍历才能获得有序数据。

综上所述,B树适合随机检索,B+树适合顺序检索和范围查询。B+树通常被应用于数据库索引结构,而B树则被广泛应用于文件系统等场景。

Explain

Explain被称为执行计划,在语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,模拟MySQL优化器来执行SQL语句,执行查询时,会返回执行计划的信息,并不执行这条SQL。

Explain可以用来分析SQL语句和表结构的性能瓶颈。通过explain的结果,可以了解到如数据表的查询顺序、数据查询操作的操作类型、哪些索引可以被命中、哪些索引实际会命中、每个数据表有多少行记录被查询等信息。

【possible_keys】

这一列的结果表明查询可能使用到哪些索引。但有些时候也会出现出现possible_keys 列有结果,而 后面的key列显示 null 的情况,这是因为此时表中数据不多,优化器认为查询索引对查询帮助不大,所以没有走索引查询而是进行了全表扫描。

如果possible_keys列的结果是null,则表明没有相关的索引。这时,可以通过优化where子句,增加恰当的索引来提升查询性能。

【key列】

这一列表明优化器实际采用哪个索引来优化对该表的访问。如果没有使用索引,则该列是 null。

ORM

ORM 是Object Relational Mapping 的缩写,译为“对象关系映射” 框架。 所谓的ORM 框架就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述对象与数据库表之间的映射关系,自动将应用程序中的对象持久化到关系型数据库的表中。

PostgreSQL

PostgreSQL是一种开源的关系型数据库管理系统,是一种可扩展的、高性能的、功能强大的数据库服务器。它具有丰富的特性和功能,包括事务支持、并发控制、复制、数据完整性保护和高可用性等。它可以在各种操作系统上运行,并且有许多开发工具和第三方插件可用于支持开发和管理数据库。由于其可靠性和性能,PostgreSQL被广泛应用于各种大型企业和 Web 应用程序中。

MySQL

MySQL的引擎

MySQL有多种不同的存储引擎可供选择,每个引擎都有其独特的功能和优势。下面是一些常见的MySQL存储引擎:

  1. InnoDB:默认情况下,InnoDB是MySQL的主要存储引擎。它支持事务处理(ACID兼容),具有较高的并发性能和数据完整性。InnoDB还提供了行级锁定和外键完整性约束等功能。
  2. MyISAM:在之前的MySQL版本中,MyISAM是MySQL的默认存储引擎。它不支持事务处理,但具有较快的插入和查询速度。MyISAM适用于读密集的应用程序,如数据仓库和非事务性应用程序。
  3. MEMORY:这个存储引擎将所有数据存储在内存中,速度非常快。它对于需要频繁读写的临时数据或缓存数据非常有用,但是数据在数据库重启时会丢失。
  4. NDB(也称为MySQL Cluster):NDB是一个分布式存储引擎,具有高可用性和高性能。它可以在多个服务器上分布数据,实现了数据的复制和分片。 NDB适用于需要高度可伸缩性和容错性的应用程序。
  5. ARCHIVE:这个存储引擎用于存储大量的归档数据,它实现了高压缩比和快速插入速度。但是它不支持索引和随机读取,只适用于存储和检索大块数据。

以上只是MySQL存储引擎的一些常用选项,还有其他一些引擎可供选择,如CSV、Blackhole等。在选择存储引擎时应根据应用程序的需求和性能要求做出决策。

etcd

etcd不是传统意义上的数据库,而是一个高可用的、分布式的键值存储系统。

Etcd是CoreOS基于Raft开发的分布式key-value存储,可用于服务发现、共享配置以及一致性 保障(如数据库选主、分布式锁等)。 在分布式系统中,如何管理节点间的状态一直是一个难题,etcd像是专门为集群环境的服务发现 和注册而设计,它提供了数据TTL失效、数据改变监视、多值、目录监听、分布式锁原子操作等 功能,可以方便的跟踪并管理集群节点的状态。

  • 键值对存储:将数据存储在分层组织的目录中,如同在标准文件系统中
  • 监测变更:监测特定的键或目录以进行更改,并对值的更改做出反应
  • 简单: curl可访问的用户的API(HTTP+JSON)
  • 安全: 可选的SSL客户端证书认证
  • 快速: 单实例每秒1000次写操作,2000+次读操作
  • 可靠: 使用Raft算法保证一致性
  • 原子Compare And Swap和Compare And Delete,用于分布式锁和leader选举

键值存储

  • 采用kv型数据存储,一般情况下比关系型数据库快。
  • 支持动态存储(内存)以及静态存储(磁盘)。
  • 分布式存储,可集成为多节点集群。
  • 存储方式,采用类似目录结构。(B+tree)
    • 只有叶子节点才能真正存储数据,相当于文件。
    • 叶子节点的父节点一定是目录,目录不能存储数据。

存储机制

etcd v3 store 分为两部分,一部分是内存中的索引,kvindex,是基于Google开源的一个Golang的btree实现的,另外一部分是后端存储。按照它的设计,backend可以对接多种存储,当前使用的boltdb。boltdb是一个单机的支持事务的kv存储,etcd 的事务是基于boltdb的事务实现的。etcd 在boltdb中存储的key是reversion,value是 etcd 自己的key-value组合,也就是说 etcd 会在boltdb中把每个版本都保存下,从而实现了多版本机制。

reversion主要由两部分组成,第一部分main rev,每次事务进行加一,第二部分sub rev,同一 个事务中的每次操作加一。

etcd 提供了命令和设置选项来控制compact,同时支持put操作的参数来精确控制某个key的历 史版本数。

内存kvindex保存的就是key和reversion之前的映射关系,用来加速查询。