共计 10447 个字符,预计需要花费 27 分钟才能阅读完成。
本文首发于 Nebula Graph Community 公众号
1. 概述
过来十年,图计算无论在学术界还是工业界热度继续升高。相伴而来的是,全世界的数据正以几何级数模式增长。在这种状况下,对于数据的存储和查问的要求越来越高。因而,图数据库也在这个背景下引起了足够的器重。依据世界出名的数据库排名网站 DB-Engines.com 的统计,图数据库至 2013 年以来,始终是“增速最快”的数据库类别。尽管相比关系型数据库,图数据库的占比还是很小。但因为具备更加 graph native 的数据模式,以及针对性的关系查问优化,图数据库曾经成为了关系型数据库无奈代替的数据库类型。此外,随着数据量的继续爆炸性上涨,人们对于数据之间的关系也越来越器重。人们心愿通过开掘数据之间的关系,来获取商业上的胜利,以及取得更多人类社会的常识。因而咱们置信,天生为存储数据关系和数据挖掘而优化的图数据库会在数据库中继续保持高速增长。
图 1: 关系型和图数据库在关系查问的性能比照
图 1 显示了查问数据之间多跳关系(图的深度优先或者广度优先搜寻)的关系型数据库和图数据库的性能差别。(这里咱们尽管以 Neo4j 为例,但 Nebula 无论在性能还是在可扩展性上都是优于 Neo4j 的)。
尽管关系查问性能胜于关系型数据库,以后支流的图数据库在多跳查问(高深度图遍历)上的性能还是灾难性的。尤其对于大数据量,分布式系统来说更是如此。而存储的性能又往往是数据库性能的瓶颈。在咱们的简略测试(单机,1GB/s SSD,73GB 数据)中,简略的三跳查问并返回属性 P50 提早能够达到 3.3s,P99 提早能够达到 9.0s。而且随着查问语句的复杂度晋升,零碎很可能变得不可用。
目前,Nebula 应用 RocksDB 作为底层存储引擎。咱们晓得图数据库的次要 workload 是对于关系的多层次遍历,一次查问往往须要屡次对存储引擎的读取。因而对 RocksDB 一次读取的性能劣势在图查问中会被屡次放大。这也是为什么 多跳图查问提早微小。反过来说,对于单次 RocksDB 查问的性能晋升也将在 Nebula 查问中被屡次放大。因而如何优化 RocksDB,使得 RocksDB 适配图数据库的 workload,成为优化存储端性能的重中之重。
RocksDB 的外围数据结构是 LSM-Tree。所有 key 和 value 都存于 LSM-Tree 中。但这种设计有一个毛病:因为 value 往往比 key 大,LSM-Tree 中大部分的空间是用来存 value 的。一旦 value 特地大,那么 LSM-Tree 会须要更深的 level 来存储数据。而 LSM-Tree 的读写性能是间接跟层数负相关的。层数越深,可能带来的读写放大就越多,性能也就越差。因而咱们提出应用 KV 拆散来存储图数据库:将值较小的数据存在 LSM-Tree 中,而将值较大的数据存在 log 中。这样操作,大 value 并不存在 LSM-Tree 中,LSM-Tree 的高度会升高。而 RocksDB 相邻两层的 size 是 10 倍关系,即使缩小一层 LSM-Tree 高度,也能大大增加 Cache 的可能性,从而进步读性能。此外,KV 拆散带来的读写放大的缩小也能放慢读写速度。
在咱们的测试中,咱们发现 KV 拆散对于图查问的性能具备微小晋升。对于小 value 的查问提早升高能够高达 80.7%。而对于大 value 的查问,提早升高绝对较少,但也能够达到 52.5%。思考到大部分大 value 的数据是冷数据而且占绝大多数的,因而总体性能的晋升将更靠近于对于小 value 的查问。
值得注意的是,Nebula 从 3.0.0 版本开始曾经提供了 KV 拆散的性能。用户能够通过 nebula-storaged 的配置文件来配置 KV 拆散的性能。
2. KV 拆散技术
上文说到 LSM-Tree 存在比较严重的读写放大问题。这是因为每次 Compaction 都须要同时对 key 和 value 进行 Compaction,而且这个放大率会随着数据库的数据减少而增大(对于 100GB 数据,写放大能够达到 300 多倍)。这对 LevelDB 来说兴许不是那么重大的问题。因为 LevelDB 是为 HDD 设计的。对 HDD 来说,随机读写性能远远低于程序读写(1,000 倍差距)。只有读写放大比例小于 1,000 就是合算的。但对于 SSD 来说,随机和程序读写性能差距没那么大,尤其对于 NVMe SSD(如下图)。
图 2. NVMe SSD 性能
因而大量的读写放大会节约带宽。于是,Lu. etc 在 2016 年提出了 KV 拆散的存储构造:https://www.usenix.org/system/files/conference/fast16/fast16-papers-lu.pdf。论文的核心思想是比拟小的 key 存在 LSM-Tree 中,value 放在 log 中。这样 LSM-Tree 每一层能够存更多的 KV,同样的数据量,层级会比拟低,这样能够进步读写的效率。对于写没那么多的 workload,Compaction 时省下来的写带宽可也能够升高读的 P99 提早。当然这个设计也有肯定的问题。相比 SSTable 中的 KV 相对有序而言,log 中的 value 只是绝对有序(依照 key 排序)。因为每次插入数据都是 append 到 log 中,必须依赖后续的 Garbage Collection(下简称 GC)来使 log 中的数据也变得绝对有序。因而对于大规模的范畴查问 Range Query,并且是小 value(64B),性能可能会差。
目前 RocksDB 的最新版本曾经反对了 KV 拆散:http://rocksdb.org/blog/2021/05/26/integrated-Blob-db.html。它将拆散后的 value 存到了多个 log 上(.blob file)。每一个 SST 对应多个 Blob。Blob 的 GC 是在 SST Compaction 的时候触发。
3. Nebula KV 拆散性能测试
在这里,咱们测试 Nebula 在不同的数据和查问下的 KV 拆散的性能,包含:
- 不查问属性的拓扑查问
- 别离对小 value 和大 value 点的属性查问
- 对边的属性查问
- 数据插入
- 没有大 value 状况下 KV 拆散的影响。
3.1 测试环境
本次测试次要应用了一台物理机。Node A 具备 56 核 Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz,256GB 内存,图数据存储在 1.5 TB 的 NVMe SSD 上。
测试数据都是由 LDBC(https://github.com/ldbc)生成。为了测试 KV 拆散成果,咱们筹备了两类数据:一类全是小 value,另一类是大 value 和小 value 混合。对于前者,咱们应用默认 LDBC 的设置,如图 3。
图 3. LDBC 默认 Text 和 Comment value 设置
对于后者咱们将 text、comment、large post 和 large comment 全副设置成 min size 4KB、max size 64KB。这是属于大 value,由 REPLY_OF
边连贯。咱们保留 Person 的默认设置,属于小 value,由 KNOW
边连贯,其 value 的具体散布参考表 1。
Bucket | Percentage |
---|---|
0-32B | 2.67% |
32B-128B | 0.04% |
128B-160B | 96.60% |
160B-192B | 0.69% |
表 1. Person value 大小散布
据此咱们筹备了两个数据,见表 2。
数据集 | value 大小 | 数据集大小 | Comment |
---|---|---|---|
Data1 | < 200B Person | ||
Default for others | 37GB | scale * 30 | |
Data2 | <200B Person | ||
Min 4K, Max 64K for others | 73GB | scale * 3 |
表 2. 数据集详情
这里咱们应用 nebula-bench 中不同的测试语句,包含 1 跳、2 跳、3 跳查问和 FindShortestPath(测试中缩写 FSP)、INSERT 语句。此外,咱们还增加了 5 跳查问来测试更极限的性能状况。同一测试反复执行 5 次,后文将应用 NoSep 和 Sep 别离指代未配置 KV 拆散和配置了 KV 拆散。
3.2 KV 拆散后 RocksDB 的内部结构
咱们别离应用 KV 拆散和不拆散的形式导入数据集 Data2。对于 KV 拆散的设置,咱们设置大于某个阈值的数据存在 Blob 中(拆散),小于阈值的数据存在 SST 中(不拆散)。这里以 100B 阈值为例。
对于 NoSep,导入数据后,一共有 13GB 数据,217 个 SST。对于 Sep,导入数据后,一共有 16GB 数据,39 个 SST。图 4. 和图 5. 别离显示 NoSep 和 Sep 的 LSM-Tree 外部状况。
图 4. KV 不拆散 RocksDB 有三层 LSM-Tree
图 5. KV 拆散后 RocksDB 有两层 LSM-Tree
能够看到 NoSep 应用了 3 层 LSM-Tree,而 Sep 只有两层。思考到咱们配置 RocksDB L1 为 256MB,L2 为 2.5GB,L3 为 25GB。单单层数从 3 层缩小到 2 层可能就是是否将所有数据存入 Cache 的区别。
3.3 拓扑查问的性能
对于图的查问既有属性查问也有拓扑查问。首先,咱们测试 KV 拆散对于非值(拓扑)查问的影响。拓扑查问对 RocksDB 不会调用 GET 操作,而只有 SEEK 和 NEXT 操作。而对于拓扑查问,又分为对于 KNOW
关系和 REPLY_OF
关系进行 walk。值得注意的是,尽管这两种关系(边)所连贯的点的属性大小存在很大差异,但拓扑查问只波及边。咱们将同一份 Data2 数据集别离导入到 KV 拆散和不拆散的 Nebula 中,并且从同一个原始数据中获取查问语句进行查问。
查问性能跟 Cache 机制无关。RocksDB 次要应用了本身的 LRU Cache,也叫 Block Cache,和 OS 的 Page Cache。其中 Block Cache 贮存的是解压缩后的 Block,而 Page Cache 贮存的是压缩后的 Block。Block Cache 尽管效率更高,然而空间使用率低。在生产环境中,咱们举荐将 Block Cache 大小设置为 1/3 内存。本次测试将别离比拟不应用 Block Cache(只有 OS Page Cache),1/ 3 内存(80GB)大小的 Block Cache + OS Page Cache,和 direct I/O(既没有 Block Cache,也没有 OS Page Cache)各自的性能。
图 6. KV 拆散对于 KNOW 关系拓扑查问的性能影响
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.9% | 1.0% | 0.7% |
Go 2 Step | 4.7% | 5.3% | 5.1% |
Go 3 Step | 15.9% | 21.4% | 9.4% |
Go 5 Step | 11.2% | 12.2% | 7.9% |
FSP | 6.8% | 10.1% | 2.7% |
表 3a. KV 拆散对于 KNOW 关系拓扑查问的提早缩小(Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 1.2% | 1.1% | 1.5% |
Go 2 Step | 8.3% | 10.0% | 7.1% |
Go 3 Step | 26.8% | 43.2% | 29.6% |
Go 5 Step | 31.7% | 38.3% | 21.6% |
FSP | 8.6% | 12.4% | 3.9% |
表 3b. KV 拆散对于 KNOW 关系拓扑查问的提早缩小(Block Cache + Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 1.1% | 1.0% | 1.8% |
Go 2 Step | 14.3% | 15.0% | 12.4% |
Go 3 Step | 17.4% | 17.8% | 16.0% |
Go 5 Step | 10.5% | 3.0% | 17.2% |
FSP | 15.8% | 21.7% | -3.6% |
表 3c. KV 拆散对于 KNOW 关系拓扑查问的提早缩小(direct I/O)
图 6 和表 3 显示了 Nebula 对于 KNOW
关系查问的测试后果。针对数据集 Data2 的数据分布个性,咱们测试了别离以 100B 和 4KB 作为 KV 拆散的阈值。能够很显著地看到 KV 拆散极大地晋升了 Data2 的查问性能。对于图遍历深度较浅的查问(Go 1 Step),KV 拆散的提早升高比拟少,在 100B 阈值下的 P50 提早升高大概在 1%。但对于更深的查问,其晋升就非常明显了,比方:对于 Go 3 Step,在应用大 Block Cache 下(表 3.b),在 100B 阈值下 P50 提早升高能够达到 43.2%。而寻找最短门路对于图的遍历的深度往往在 1 跳和多跳查问之间,因而其性能晋升是多跳查问的均匀。
留神这里 KV 拆散在 Go 5 Step 并没有进一步的性能晋升,可能因为对于更深的遍历,其次要瓶颈不在存储。相比于 KV 拆散之于不拆散的性能晋升,100B 和 4KB 的阈值区别并不大。因而在表 3 中,咱们以 100B 阈值为例展现了具体的提早缩小百分比。
另外,对于有 Cache 的状况下(Block 或 Page Cache),所有数据都能够缓存,此时 KV 拆散性能比不拆散性能更好,也阐明 KV 拆散后内存中的数据拜访效率更高。具体的起因可能是 SST 原本就不是内存拜访的最佳数据结构。因而小 LSM-Tree 相比大 LSM-Tree 带来的性能晋升会比拟显著。
图 7. KV 拆散对于 REPLY_OF
拓扑查问的性能(留神这里 Go 3 Step 和 Go 5 Step 之间性能并没有多大差异。这是因为 Go 5 step 只有 0.6% 的查问返回了非 0 后果。因而 Go 5 Step 实质上不会比 Go 3 Step 多 walk 多少边。)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 1.1% | 1.8% | 0.1% |
Go 2 Step | 1.2% | 1.3% | 1.1% |
Go 3 Step | 1.2% | 1.4% | 0.8% |
Go 5 Step | 1.1% | 1.2% | 1.0% |
FSP | 6.4% | 9.1% | 3.3% |
表 4a. KV 拆散对于 REPLY_OF 关系拓扑查问的提早缩小(Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.8% | 0.9% | 0.2% |
Go 2 Step | 1.2% | 1.4% | 0.2% |
Go 3 Step | 1.3% | 1.6% | 0.4% |
Go 5 Step | 1.3% | 1.6% | 0.7% |
FSP | 5.4% | 8.0% | 2.4% |
表 4b. KV 拆散对于 REPLY_OF 关系拓扑查问的提早缩小(Block Cache + Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 1.2% | 1.4% | 0.2% |
Go 2 Step | 1.3% | 1.7% | 0.0% |
Go 3 Step | 1.3% | 1.5% | 0.6% |
Go 5 Step | 1.8% | 2.0% | 0.7% |
FSP | 9.1% | 13.3% | -4.3% |
表 4c. KV 拆散对于 REPLY_OF 关系拓扑查问的提早缩小(direct I/O)
图 7. 和表 4. 展现了对于 REPLY_OF
关系的查问后果。此时,能够看到 KV 拆散尽管性能晋升成果不显著,但也是有确定的晋升的。留神这里 Go 3 Step 和 Go 5 Step 之间性能并没有多大差异。这是因为 Go 5 Step 只有 0.6% 的查问返回了非 0 后果。因而 Go 5 Step 实质上不会比 Go 3 Step 多 walk 多少边。留神这里因为性能差异不大,咱们只展现了 4K 阈值下 KV 拆散和不拆散的比照状况。
3.4 点的属性查问性能
在这部分,咱们来测试 KV 拆散对于属性(值)查问的性能影响。依照 KV 拆散的实践,传统的 LSM-Tree 对于读性能的影响次要来源于读放大。而读放大要通过 GET
操作能力体现得显著。而属性查问恰好能体现读放大的影响。
首先,咱们测试对于点的属性查问。同上,测试分为对于小 value 和大 value 进行 walk。
图 8. KV 拆散对于小 value 属性查问的性能
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 36.2% | 37.6% | 32.4% |
Go 2 Step | 34.0% | 35.5% | 28.6% |
Go 3 Step | 37.4% | 40.3% | 29.3% |
Go 5 Step | 16.3% | 19.0% | 14.3% |
表 5a. KV 拆散对于小 value 属性查问的提早缩小(Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 35.6% | 37.8% | 31.6% |
Go 2 Step | 29.6% | 31.1% | 23.4% |
Go 3 Step | 33.8% | 36.0% | 25.4% |
Go 5 Step | 19.1% | 33.5% | 9.9% |
表 5b. KV 拆散对于小 value 属性查问的提早缩小(Block Cache + Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 78.6% | 78.9% | 77.9% |
Go 2 Step | 80.8% | 81.3% | 78.7% |
Go 3 Step | 75.8% | 77.3% | 72.1% |
Go 5 Step | 53.2% | 46.3% | 37.5% |
表 5c. KV 拆散对于小 value 属性查问的提早缩小(direct I/O)
图 8 和表 5 显示了 KV 拆散对于小 value 进行 walk 并返回值(属性)查问的性能影响。这是通过对 KNOW
关系进行查问并返回节点属性实现的。咱们能够看到以 4K 为阈值状况下,KV 拆散 P50 提早升高能够达到 81.3%,而 P99 提早升高能够达到 78.7%。这次要得益于对于 KV 拆散对于点查问的性能晋升微小,这也和 RocksDB 对于 KV 拆散的测试后果统一。另外,能够看到 KV 拆散对于 direct I/O 的性能晋升最大。这是因为 KV 拆散对读性能的晋升次要来源于读放大的缩小和 Cache 命中率的晋升。但因为磁盘 I/O 性能远小于内存拜访,所以读放大的减小对于性能晋升更加显著。而读放大只在产生 I/O 的状况下才会产生。所以这里 direct I/O 次要是体现读放大的减小对于性能的晋升。
图 9. KV 拆散对于大 value 属性查问的性能
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 7.1% | 6.7% | 8.8% |
Go 2 Step | 3.8% | 4.2% | 3.8% |
Go 3 Step | 1.9% | 1.8% | 1.6% |
Go 5 Step | 0.5% | 1.0% | -0.6% |
表 6a. KV 拆散对于大 value 属性查问的提早缩小(Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.7% | 0.5% | 1.3% |
Go 2 Step | 0.9% | 0.9% | 1.0% |
Go 3 Step | 1.5% | 1.6% | 1.6% |
Go 5 Step | 1.4% | 1.7% | 1.0% |
表 6b. KV 拆散对于大 value 属性查问的提早缩小(Block Cache + Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 52.3% | 52.5% | 51.1% |
Go 2 Step | 26.4% | 22.9% | 24.3% |
Go 3 Step | 7.6% | 1.0% | 16.8% |
Go 5 Step | 2.4% | 2.4% | 3.8% |
表 6c. KV 拆散对于大 value 属性查问的提早缩小(direct I/O)
图 9 和表 6 通过对 REPLY_OF
关系进行 walk 并返回起点 value,体现了 KV 拆散对于读取大 value 性能的影响 。 此时 KV 拆散在比拟浅的遍历的时候,性能进步反而较大,而对于较深的遍历没有太多影响。这次要是因为对于 REPLY_OF
关系,99.99% 的查问存在 1 跳及以上关系、只有 50.7 % 的数据之间存在 2 跳及以上关系、只有 16.8% 的数据之间存在 3 跳及以上关系。因而随着查问跳数回升,须要理论去 GET 属性的查问比例反而缩小。因而对于理论 GET property 比例最高的查问 Go 1 Step,KV 拆散对于其性能晋升反而最多。而对于其余查问,KV 拆散对于性能的影响会更靠近于 3.3 节中对于 REPLY_OF
关系的拓扑查问。
3.5 边的属性查问性能
再来测试对于边属性的查问性能。依据之前的测试后果,咱们晓得 REPLY_OF
边连贯的深度比拟浅,较深的查问也会进化成浅查问。因而,这里咱们仅关注对于 KNOW
关系的边属性查问。
图 10. KV 拆散对于边属性查问的性能影响
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.5% | 0.6% | -0.5% |
Go 2 Step | 3.3% | 4.2% | 2.8% |
Go 3 Step | 11.4% | 25.8% | 1.2% |
Go 5 Step | 15.0% | 24.3% | 6.6% |
表 7a. KV 拆散对于边属性查问的提早缩小(Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.0% | 0.2% | 0.1% |
Go 2 Step | -0.3% | -0.1% | -0.6% |
Go 3 Step | 4.2% | 13.0% | -1.7% |
Go 5 Step | 0.7% | 4.7% | -0.1% |
表 7b. KV 拆散对于边属性查问的提早缩小(Block Cache + Page Cache)
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 0.5% | 0.2% | 1.4% |
Go 2 Step | 4.0% | 4.9% | 2.1% |
Go 3 Step | 12.5% | 12.9% | 10.2% |
Go 5 Step | 6.9% | 1.2% | 13.4% |
表 7c. KV 拆散对于边属性查问的提早缩小(direct I/O)
图 10 和表 7 显示了测试后果。能够看出此种状况下 KV 拆散的性能晋升大大降低。因为在 LDBC 数据集中,边上的属性只有 creationDate,小于测试中 KV 拆散的阈值 100B。因而无论是否应用 KV 拆散,边上的属性都存储在 LSM-Tree 上。只是 KV 拆散后,LSM-Tree 的大小变小,Cache 效率更高。因而,KV 拆散对于 LDBC 数据集中的边上属性查问性能晋升较小。
3.6 数据插入的性能
这里,咱们也测试下 KV 拆散对于数据插入的性能影响。因为 Cache 对于 RocksDB 的 PUT
的性能影响不大,这里只测试了只有 OS Page Cache 的场景。咱们持续应用数据集 Data2,并且每次插入查问都运行 10 分钟,以确保 Compaction 会被触发。
图 11. KV 拆散对数据插入的性能影响
图 11 显示了数据插入性能。一个是插入 Person 数据,属于小 value。另一个是插入 Comment 数据(至多 4KB),属于大 value。咱们能够看到 KV 拆散对于插入大 value 具备比拟显著的性能晋升。其收益次要来自于更少的 Compaction。而对于小 value 的插入,由 PUT 导致的写放大在 RocksDB 中并不显著。但另一方面,在每一个 KV Flush 到 L0 的时候,KV 拆散带来的额定一次写的开销(须要同时写 SST 和 Blob)却比拟显著。因而,在 value 比拟小的时候,KV 拆散的写性能会受影响。
3.7 如果我的数据集全是小 Value?
咱们曾经晓得 如果数据集中有大 value,那么无论是拓扑查问还是值查问,KV 拆散都能带来微小的性能晋升。那如果没有大 value 呢?是否存在副作用?
这一节咱们测试了 KV 拆散对于没有大 value 状况的性能影响。
首先须要留神的是,KV 拆散并不是在任何时候都能对 RocksDB 带来性能晋升。尤其在小 value 状况下,Range Query 性能是会变差的。咱们这里测试也不会笼罩所有小 value 的状况。咱们抉择应用数据集 Data1,针对默认的 LDBC 数据进行测试。
图 12. KV 拆散对小 value 拓扑构造和属性查问的性能影响
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 3.2% | 3.5% | 2.5% |
Go 2 Step | 5.1% | 7.0% | -1.4% |
Go 3 Step | 2.1% | 3.5% | 0.4% |
FSP | 2.6% | 3.7% | 1.1% |
表 9a. 所有小 value 查问的提早升高
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Test | Avg reduction | P50 reduction | P99 reduction |
Go 1 Step | 0.2% | -1.5% | 7.7% |
Go 2 Step | 11.2% | 9.3% | 19.2% |
Go 3 Step | 3.4% | 1.6% | 8.2% |
FSP | 5.9% | 8.3% | 1.9% |
表 9b. 所有小 value 查问的提早升高
Test | Avg reduction | P50 reduction | P99 reduction |
---|---|---|---|
Go 1 Step | 17.8% | 19.1% | 15.1% |
Go 2 Step | 22.2% | 24.9% | 19.1% |
Go 3 Step | 58.1% | 68.1% | 28.1% |
FSP | 26.2% | 35.6% | 3.2% |
表 9c. 所有小 value 查问的提早升高
图 12 展现了在全是小 value 状况下,将 KV 拆散的阈值置成 100B 的性能。其中,在 Go 1 Step、Go 2 Step、Go 3 Step 中,咱们提取了指标节点的属性,是属性查问,FindShortestPath 是不返回值的拓扑查问。能够看到,尽管性能晋升不如数据集 Data2,然而提早也是有升高的,在 direct I/O 状况下尤为显著。留神,咱们这里没有展现 Go 5 Step,因为 Go 5 Step 的压力测试中呈现了超时状况,因而测试后果不精确。
总之,咱们证实了无论是大 value 还是小 value,拓扑查问还是值查问,KV 拆散都是能带来性能晋升的。
4. 论断
咱们提出应用 KV 拆散来存储图数据库:将值较小的数据存在 LSM-Tree 中,而将值较大的数据存在 log 中。这样因为大 value 并不存在 LSM-Tree 中,LSM-Tree 的高度可能因而升高,减少 Cache 的可能性,从而进步读性能。哪怕不思考 Cache,KV 拆散带来的读写放大的缩小也能放慢读写速度。在咱们的测试试验中,咱们发现 KV 拆散对于图查问的性能具备微小晋升。对于小 value 的查问提早升高能够高达 80.7%。而对于大 value 的查问,提早升高绝对较少,但也能够达到 52.5%。思考到大部分大 value 的数据是冷而且占绝大多数的,因而总体性能的晋升将更靠近于对于小 value 的查问。从 Nebula Graph 3.0.0 版本开始,能够通过 nebula-storaged 的配置文件来配置 KV 拆散的性能。
交换图数据库技术?退出 Nebula 交换群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~
关注公众号