【Redis入门】关于磁盘,IO,数据库的简单介绍
文章目录
- 数据库引擎介绍
-
- [1.网址:db-engines.com/en/](#1httpsdbenginescomenhttpsdbenginescomen_74)
前言
在计算机中,数据存在磁盘里,在磁盘的维度里有两个指标:寻址(m/s)、带宽(G/M);在内存的维度里也有两个指标:寻址(ns)、带宽(很大),在寻址上磁盘比内存慢了十万倍。I/O buffer:成本问题,磁盘有磁道和扇区,一扇区512Byte。如果一个区域足够小,带来一个成本变大(索引)。操作系统,无论读多少数据,都是最少4k磁盘中拿。
常识介绍
1.磁盘
首先在计算机当中,数据是存在磁盘里的。那么以磁盘的维度它有两个指标,第一个是寻址,寻址的速度是毫秒级的,然后第二是带宽,也就是说单位时间可以有多少个字节流过去,多大的数据量流过去,然后基本上是G或者M这种级别,比如说多少G或多少M,几百兆或者一两G这么这样的一个带宽速度,这是磁盘带来这样的一个基础知识。
2.内存
内存它有一个寻址,它的寻址是纳秒。那么这个时间单位里,一千分之一秒是毫秒,一千分之一毫秒是微秒,一千分之一微妙是纳秒。这应该都知道,所以你现在得出一个基本的常识,就是在磁盘当中获取数据。
3.IO
I/O buffer,然后buffer是什么意思?我就用了一个buffer,首先其实这是一个成本问题,什么叫成本问题?磁盘有磁道和扇区,一个扇区多少字节?是512个字节。那么这个时候注意有一个成本问题,如果我们访问一个硬盘这个硬件的时候,都是最小力度以一个扇区一个512来找,那么一块硬盘是不是1t、2t,是不是会有很多512?那么每一个512在哪?我的数据在哪一个512里面放着呢?那么这样你要明白一个点,就是一个区域如果足够小,那么它一定带来一个成本变大,索引成本变大。
也就是你如果一个1t里边都是512字节这么一个一个小格子的话,那么你上层操作系统当中得准备1个索引,这个索引就不是4个字节了,可能得8个字节或者很多个字节,他要一个能表示一个很大数的区间,才能索引出这么多的512个小格子,所以成本会变大,索引会变大。所以造就了一个东西,在我们格式化磁盘的时候,有一个4k对齐对不对?也就是真正使用硬件的时候,并不是按照512个字节为一次读写量,他会把这个变得更大一点,你读一个自己读512、读一k他给到硬盘了,硬盘都是咣当给你返回4k,你看512跟4k就差了很大,它俩大小就不一样了, 那么一个硬盘512很多小点点,4k可能在这变少,那么这时候其实索引的体量大小就会随着变化,所以一般磁盘都是默认格式化4k操作系统,无论读多少都是最少4k从磁盘拿的,这个知识点这都是技术常识。
数据存储发展进程
1.数据存在文件里
文件中的数据以data.txt为例,linux可用命令grep、awk,java可写一段程序,做一个基于文件的I/O流读取查找。随着文件变大,速度变慢的原因是硬盘(I/O)成为瓶颈。
2.数据存在磁盘数据库里
第一,有了一个data page概念。他的data page大小是4k,现在如果再跟你说,如果你有一张表在数据库里边,你建一张表,里面那么多行,存到磁盘的时候,他其实在物理存的时候,好像用了很多4k这样的一个小格子,那么这个4k刚好和我们硬件的磁盘里边的4k正好能对上,所以这时候如果我们的数据库准备很多这样的4k,也就是曾经数据是线性在一个文件里边,它虽然到底层的时候还是4k,但是这一批文件混在了一起,4k连起来了,不能把他们割开,找不到他们在哪,但是如果现在我在上面软件里边先定义出一个4k,然后每个4k有自己的Id,0号、1号、2号,且你要读取4k里边某个数据,正好符合你磁盘一次的I/O,也没有浪费这个I/O。
你可以把它变得更小,比如变成1k但你会发现你上层软件数据库想读1k的时候,硬盘是不是还是读4k?索性你还不如直接上面也是4k,反正你要查什么东西的时候,从我上面就调某一个对的位置了,底层就把这个拿出来了。然后比他大可不可以?比如我定义成8k、16k可不可以?定义小了会有浪费,定义大了无所谓。可以往大处调一点,但是调小的话其实浪费了。
因为你读1k底层还是走4k没必要。那么这样的话,注意这是第一个知识点,它会分成很多小格子,那么曾经这个文件里边可能1万行、10万行就散在了这么多的小格子里边,但是这个时候如果光有4k这种小格子的话,其实你查找数据的成本复杂度还是和前面一样,为什么?因为你还是要从第一个4k先读到内存,然后再读到内存,挨个去找,所以他走的还是全量I/O,跟前面I/O量是一样的,所以他一定会很慢。
第二,那么数据库怎么样可以让它变快?也就是建表,如果你使用数据库只是建表了,没有去建索引的话,其实那时候根本不可能出现任何提速,速度一定会很慢。所以数据库里边有另外一个东西就是索引,索引其实也是使用的4k这种存储模型,无非就是4k格子前面里边放的是一行一行的数据,然后这后面4k里边放的就是那行里边你面向的某一个列,比如身份证那一列。
我就把身份证那列数据拿到前边4k里边,每一个身份证号指向的是哪一个的data page,有一个指向关系,这就是所谓的索引。所以你数据变大的话,那么索引肯定也会很多。一定要明白一个概念,数据是用4k、4k去存的,然后你的数据如果没有索引的话,查询速度还是很慢,如果想提升这个速度,你就必须建一套索引系统,索引系统其实变相来说它也是一笔数据。
第三,然后这还有一个知识点,就是在我们建关系型数据库表的时候,关系型数据库一般是用什么存储方式?在建表的时候必须给出什么?必须给出schema,就是必须给出这个表一共有多少个列,每个列,它的类型是啥?约束是啥?那么这里边的每一个列的类型其实就是字节宽度。比如说我第一列是varchar(20),那么第一列未来它一定会开辟20个字节。
那么一个表为什么在使用之前要先给出schema,只要schema给出、类型都给出之后,那么这个表里边的每一行的数据宽度就已经定死了,未来如果你像这张表插入了一行,假设这一行有10个字段,你只给出第一个和第7个,剩下的字段都没有给,但是向data page里去放的时候,第1个和第7个以及其他那些没有值的、那些字节都会就会用0去开辟,用空的东西去补充那些字节,那么这样会有一个什么好处?
首先表里边有这个概念,然后存的时候更倾向于行级存储,以行为单位来存,为什么?如果你给出schema了,给出宽度,那么我这一行假设有10个字段,每个字都是4个字节的话就40个,即便你只给了其中一个字段有值,那么剩下的30多个我也会占空,把这一行位置站出来占位。占位这样一个好处,就是未来你的增删改,你比如在向其他地方补充的时候,你不用移动数据,直接拿你新的数据在那个位置复写就可以了。也就是数据库关系型数据库表是行级存储的,然后数据是数据,索引也是数据。
但是这时候有了索引之后,其实还差一个东西,为什么?你还要注意一点,就是数据和索引其实都是存储在硬盘当中的,然后这时候真正查的时候是要用到一个东西,就是在内存里边准备一个B+树,内存是速度最快的地方,所以在内存里边准备了一个B+树, B+树所有的叶子就是这些4k小格子。B+树其实数干是在内存里的,比如说的区间和偏移,然后这个时候如果用户想查,只要你查询的时候,注意索引在where条件里,只要命中索引了,那么这个查询在B+树会走树干,最终找到某一个叶子,比如你的身份证号,刚好在叶子代表这个区间里,那么把它从磁盘读到内存,把它解析完之后,最笨的方法,遍历完了之后,可以知道应该下一次把哪个data page放到内存里边读进来,那么就可以找到我们那笔记录了。最简单的B+树如果复杂的话,你就想二叉树,中间如果是8的话,左边是小于8的,右边是大于8的。如果你要查22的话,是不是一定走右边这条路?所以树干的话一定会沿着一个最小的方向去找,最终找到一个叶子,叶子里边可能给定区间是从930,你22一定出现在里边,但是930这些明细记录是在磁盘的小格子里的,你需要从磁盘读到内存,如果把这些索引再堆到内存里的话,你的内存不够,存不下这些索引,所以索引和数据都放在磁盘,内存里只存一个树干,只存一些区间,就这么讲就可以了。这样的话是充分利用了各自的能力,磁盘能存很多东西,然后内存速度快,然后用一种数据结构可以加快你的遍历的一个查找的速度,然后数据又是分而治之的存储,所以这时候你获取数据速度极快,最终的目的就是为了什么?减少I/O的流量。磁盘有这么多缺点,那么我就不让它发生大量的I/O以及减少寻址这个过程,明白了吧?那么这是我们的所谓的数据库。
当这个理解之后注意,随着数据量的变大,假设这张表我不止这么几个data page了,这张表本身涨到几千亿行几万亿行,或者几百万行,数据量变大的时候变成1t、2t了。那么这时候你都应该听过这样的一句描述,就是数据库的表如果很大,检索速度、检索性能一定会变低,对不对?那么这句话如果没什么问题的话,应该怎么去答?如果输入的表行很多,性能就会降低,对不对?
那么这句话在回答的时候你要小心了,首先增删改,如果表有索引,然后增删改变慢,因为你要增删改里面数据的话,这个数据你建了多少个索引都会找索引列,所以你必须去修改索引或调整它的位置,就是维护索引会让你的增删改变慢。但是查询速度会不会变慢呢?那么这时候你要两答:
第一答:假设我这个表100个t,硬盘就能装下100个t,然后内存也刚刚把所有的树干都能存下,然后哪都没有溢出,哪都没有问题,那么这时候注意,来了一个人的一条简单查询,且他where条件能够命中索引。那么这时候,如果一个或少量查询,依然很快。就是一个查询进来之后,因为你where条件走的还是内存B+树,走的还是一个索引块,这个索引块到内存依然走的是一个data page,他并没有说,你数据量变大,我未来会把别的data page也要带到内存里面去。
但是什么时候会查询的时候速度会变慢,也就是说当并发,很多的查询都到达了,或者一个复杂的查询到达了,那么这时候查询的时候不是要获取一个的data page到内存了,因为你数量变大,数据量越大,能够被很多查询命中的几率,被不同命中的几率就会很大。所以这个时候会受硬盘的带宽影响速度。也就是说假设来了1万个查询,每个查询查一个4k,每个人查条件都不一样,刚好是又散在不同4k上。那么这1万个查询进入到这条服务器之后,这1万个的每个4k是挨个的向我们内存去走的,查一个,走一个。那么这时候有一部分人就会等待前面那些个4k,他们走完之后才能轮到自己。
假设都是B+树不受影响,顶层还可以。因为你一定要明白硬盘的慢,除了寻址慢,是不是还有一个带宽,所以这两点你都要说出来,把哪个少说了,其实都是少覆盖了一个范围。
那么数据库分库、分表、分治、分布式,那个事情先不去描述它,那么如果说数据库已经使用磁盘了,那么这个时候其实尤其到后边查询这也发现了,如果数据量特别大的时候,它就一定会对增删改查,尤其在并发下的时候,它查的速度都会同等下降,都会变慢。那么这个时候如何去解决这个问题呢?
3.数据存在内存数据库里
那么首先看一个极端,这个极端是SAP这家公司有一个HANA数据库,这是一个内存级别的关系型数据库。他们给提的方案和报价,内存是两个T,因为它是内存的关系数据库,内存大了,相对应的这台计算机不可能一个大,其他都低,所以CPU的核心数,然后网卡好像就几千块钱一块,然后整台机器硬件,再加上他的ERP软件,加上HANA数据库,售价是两个亿,当时我就记住这么一个套餐了,是两个亿,他们的销售当面给我们解释的,就是两个亿,因为他的硬件都是跟英特尔定制的。那么这样的话,其实这个是两个极端,一个是都是关系型数据库,一个是拿硬盘作为数据的主存储区域,一个是拿内存做数据主存储区域,然后这两者的速度一定是内存是最快的。
这还有一个小常识,数据在磁盘和内存体积不一样,什么叫数据在磁盘和内存体积不一样?你要明白在磁盘当中是没有所谓的指针的概念的,数据是不可能出现一个所谓像我们对象一样,我堆里就一个对象,我可以不同的线程里边或不同的地方有不同的引用。如果数据想出现在索引,那么就在这一定会出现,然后他是原本这还得有一个,所以这个数据一定会涨出。所以如果关系型数据库使用磁盘存了两t数据,那么如果迁移到HANA的数据库的话,到内存里边的不是2t,可能1t多一点,因为你这边不用去建一套索引。而且它可以启动一些压缩优化的策略。
4.缓存的引入
缓存,因为内存级的我买不起,然后我还得使用磁盘级的,但是我磁盘级特别慢,那么我就用小一点的内存,把一些数据迁出来,那么缓存的概念就被提出了,缓存里的技术有很多,比如说memcache、redis。
5.基础设施
有两个基础设施,一个是冯诺伊曼体系的硬件;一个是以太网和TCP/IP的网络。目前的所有信息系统,两个最基本的基础设施,这两个基础设施没有改变,所以redis才能出现,如果现在硬件不是冯诺伊曼体系体系,什么量子计算机出现了,然后所有的硬盘、I/O、带宽的问题都解决了,那么估计就没有人再用redis,memcache做缓存这个事了。另外一个以太网和TCP/IP的网络,这种网络潜台词就是不稳定,所以这个时候如果你曾经用一个技术,现在要整合多个技术的时候,那么就一定会带来一些问题,数据一致,双写等等很多问题。所以后边知识讲的时候,这两个一定要埋在心里。
数据库引擎介绍
1.网址:db-engines.com/en/
2.数据库排名(全部数据库排名)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!