当前位置: 首页 > 原理解释

leveldb原理-leveldb 底层原理

如何查数据库快不?先别整那些虚头巴脑的理论,咱直接拿个例子,看看你的数据到底存哪儿,如何拿出来的。 我在写代码时遇到一个坑,用户想把一个用户 ID 存进去,然后立马查出来。我第一个想法肯定是直接存到内存,就像把数据倒进一个软盘里。但这招不中啊,用户写脚本的时候可能一秒钟就挂了,要么内存不够,更是时常撞车,重复就数不了了。
那我把数据存到了硬盘上,还自带索引,这样能快一点。结局用户写脚本的时候,后台机器起不来,还时常报毛病。等到用户程序员来了,我把脚本跑了一遍,发现数据都存有了,可是用户如何查都找不到。 这情况在数据库开发里叫“读性能”。我的脚本是逐条读文件的,数据可能都存有,但用户操作起来像跑了八百米。
后来我改了一下,不再每来一条数据都新建一个文件,而是把数据存到“分片”里,每个分片负责一块区域。
这样用户访问某个分片时,只有他那一块被加载到内存里,其他分片都不动,这样查询速度就稳了大量,哪怕有 100 万条数据,查起来也挺快。 还有,要是用户想查某个用户 ID,直接去整个磁盘里扫一遍那忒慢了。我只能根据 ID 在内存里找个“索引”,这索引就像一本目录,告诉 JVM 在哪块内存空间里存数据。用户请求进来,先查这个索引,找到对应的文件,再去文件里找数据。
不过,索引这东西也不是万能的。
要是文件挺大,索引本身也会变得挺占内存。
这时候,用户要是想查别的文件,就得重新加载索引,要么干脆换个文件去重新建索引。 还有个小情况,要是某个用户 ID 挺长,比如包含了大量个汉字,我再查的时候,索引就得重新算一遍,这可能会变慢。
这时候我就得把数据切分成更小的块。
比如我把一个长的 ID 分成两块,要么切成四块,每块自己建一个索引。用户查的时候,就查对应的那一小块,速度就快了。
这种“分块”的思路,在数据库开发里贼常见,就像把一个大单词切成拼音,用户只查拼音对应的音节。 再比如,用户想查两个用户 ID,比如用户 A 和用户 B。
要是我把数据按顺序存,用户查 A 只需求读前两块,查 B 只需求读后两块。
要是我把数据按 ID 排序存,查 A 和查 B 时,读的数据块是一样的,也就是用户就得读一次数据。
这时候我就把数据存成“键 - 值对”,用户查的时候,只要找到对应的键,值就在那里。 不过,我也遇到过难题。
比如用户存了 100 万个用户,每个用户 ID 都是长字符串,查的时候得读大量内存。
这时候我就得把用户按 ID 排序存起来。
这样用户查 A 时,就只读前几块数据,查 B 时,只读后几块。
这样查速度就快了。但这样有个难题,要是用户存的数据大量,按 ID 排序会把数据全体读一遍,这时候我再查 A 和查 B 就得重复读数据。
故此我又得把数据分成更细的块,每个块里排序。
这样用户查 A 时,只读对应的那一排序块,查 B 时也只读对应块,这样速度就更快了。 还有个难题,要是用户存了 100 万个数据,我按 ID 排序存,索引就得按 ID 排序。用户查 A 时,索引也得按 ID 查,这样数据就重复读了。
这时候我就把数据分成更细的块,每个块里排序,索引也分成更细的块。
这样用户查 A 时,只读对应的那一排序块,查 B 时也只读对应块,这样速度就更快了。
不过,要是用户存的数据大量,按 ID 排序会把数据全体读一遍,这时候我再查 A 和查 B 就得重复读数据。 这时候我就得把数据分成更细的块,每个块里排序,索引也分成更细的块。
这样用户查 A 时,只读对应的那一排序块,查 B 时也只读对应块,这样速度就更快了。 实际上,数据库开发里还有大量细节,比如索引如何维护,数据如何压缩,还有用户如何写脚本。
这些细节别看关键,但咱们今天先不深究,先把这个“分块、排序、索引”的根本逻辑搞清楚了。 总而言之,数据库开发里,核心就是如何快速找到数据。把数据分成块,按块排序,然后建立索引,这样用户查的时候,就只读相关的数据块,速度就快了。自然,数据量挺大时,就得把数据切得更碎,这样索引也能更细,查询也就更快了。
这就是为啥我们总在改代码,为啥时不时得重启服务器,为啥总要优化那些索引。
相关标签:

猜你喜欢

热门阅读

  • 赖柴尔定理-赖柴尔定理
  • 迪拜哪个国家的城市?-迪拜在哪国城市
  • 李毅吧番号及出处-李毅吧番号及出处
  • 贴春联的由来简介50字-春联由来简述
  • 思乡的名言和出处-思乡名言及出处

其他分站