从文件存储到数据库存储
文件存储
在计算机中,一切信息的存储都是以文件的方式固化在磁盘上。这是最基本、最简单的存储方式。
很早之前,我们的所有数据只能用文件来存储,查询数据就来读取文件。如 linux 系统中命令 grep、awk。
但有一些约束严重限制了这种存储方式查询的效率。这种限制主要来自于磁盘的读取效率。
磁盘的常识:
- 磁盘的寻址速度是毫秒级别;而内存的寻址速度是纳秒级别。
- 磁盘的带宽/吞吐,一般好的是在百兆级别。
磁盘寻址:磁头先找到 0 磁道 -> 找到分区表 -> 根据偏移量找到文件 -> 读取文件数据。
带宽/吞吐,磁盘到内存的一秒的吞吐量。一般磁盘是 百兆 级别
随着文件的变大,查询速度急剧下降。其主要原因就是:数据文件需要全部读入内存,数据需要进行全量扫描(全量 IO)。
数据库的出现
datapage 的概念
如 Redis 的 datapage 默认为 4k,将一个数据文件每 4k 分为一个 datapage 进而实现“分治”。内存在读取数据时,会以 4k 为单位进行数据读取。这个单位可调,太大索引效率会变低,太小索引占内存太大,造成浪费。
关系型数据库建表 Schema
关系型数据库建表必须给出 Schema,给出类型。这时即使插入数据行只有一个字段有值,其他空值仍会占用空间。数据二维对齐,便于搜索。
SQL 中的约束
约束:这个表中的某一个数据,只能是其他表中的某一个字段。这就是一个小对大的一个参照。能让搜索更有效率。将部分热数据放在内存,而冷数据放在磁盘上。
索引
索引,索引也是数据,也存在 datapage 中。索引将查询的关键字(id)和数据所在 datapage 的位置(内存)存储起来。所以我们可以先遍历索引,找到数据存在的大致位置,再查询。但随着数据量变大,索引也会变大。
B+ 树存索引利用内存
B+ 树,树干在内存,叶子节点是在磁盘。从而利用内存搜索更快,从而完成了整个索引。
至此为止,思考一个问题:在使用数据库时,是不是表起来越大,搜索越慢?
答:不一定。
应该这样想:数据很大,同样也维护了很大的索引,但索引主干是在内存中的。所以:
- 如果你的搜索恰好命中索引,那数据量很大对查询不会影响很大;
- 若未命中索引,查询一定会很慢;
- 而对于写的话,因为每次插入数据,都需要重新维护索引,所以将导致写的速度会变慢;
- 而对于复杂查询,又在高并发场景下,查询可能就会有问题了(Query Cache)。
Query Cache 是数据库做的一个优化,参考。它会缓存查询结果,当相同的 select 语句到来时直接从缓存中返回数据。
插曲:db-engines 网站,查看数据库排名,并参考做数据库选型。Redis 是 Key-Value 型数据库的第一名。
Redis 与 Memcache
相同点:他们都是基于 Key-Value 类型的内存型数据库。
不同点:memcache 只能存 string,而 Redis 基于 string 有其他类型,且基于类型有了方法。
注意:Redis 和 Memcache 最大的不同不只是在于支持类型的不同,而是在于 Redis 基于类型有了方法,有了方法后就可以操作各类型中具体的元素。
他们的具体区别:虽说有 String 就能存 json 格式的数据,但 memcache 无法取出所存数据的某一部分数据,即 memcache 只能取出了其全量数据(数据向计算移动)。而 Redis 可以(计算向数据移动)。
比如用 memcache 用 json 的字符串表示一个 list,但它无法取出指定的一个元素的数据(如 k[1]
)。
数据向计算移动:拿到数据再计算。数据全量取出后,再由客户端来计算。
计算向数据移动:先计算好拿哪个,再去拿数据。客户端只需要指明公式,由数据库取数据时自己计算要取的值并返回。
Linux 实用技术
strace 工具:抓取进程对内核的系统调用
linux strace
工具,可以抓取进程运行时对系统调用的日志。
使用方法:
strace -ff -o path/to/filename ./server_name
-
-ff
无论这个进程创建多少线程,都将它们落成一个文件。 -
-o
后面指定落成的文件的目录及文件前缀名。 -
sever_name
是要追踪的进程。
程序将会把 server_name
进程执行的所有系统调用日志,输出到 path/to/filename.PID
文件中。
在进程运行的同时,你可以到 /proc/PID/
目录下看各 PID 的运行情况。
如在已经监听的 redis-server 中,用一客户端执行
BGSAVE
(一个持久化命令),则会发现日志文件会多出一个。而此时(未执行命令时),在主线程中可以看到一个频繁执行的函数,即epoll
函数(引出正文 Epoll 讲解)。由此可以看到 Redis 启动了多个线程。那为什么我们广泛得说 Redis 是单线程的呢?这是因为我们常说的单线程是指 在业务处理时 是单线程来处理的。
其实在 linux 系统中没有线程的概念,其实都是进程,而在 linux 中是轻量级的进程。
Linux /proc/PID
目录
Linux 中 /proc/
目录中存了各个进程运行的相关日志。运行的进程以进程号(PID)为文件夹名存放。
附:
- 掘金上找到一篇学习来源十分相似的一篇文章
- 文档来自于马士兵课程: 不要小看一个redis
网友评论