Redis中字符串(string)与散列表(hash)比较

前面的博文Redis字符串(string)使用Redis散列表(hash)使用中,可以看到,字符串中有set、setnx、get、incrbyhe、incrbyfloat命令,散列表中有对应的hset、hsetnx、hget、hincrby、hincrbyfloat命令,如此来看,字符串和散列表确实有很多功能相似的命令。

字符串命令和散列命令比对

对于表中列出的字符串命令和散列命令来说,它们之间的最大区别就是,前者处理的是字符串键而后者处理的则是散列键,除此之外这些命令要做的事情几乎都是相同的。

Redis选择同时提供字符串键和散列键,这两种数据结构是因为它们虽然在操作上非常相似,但是各自却有拥有不同的优点,这使得他们在某些场合无法被对方替代。

散列舰的优点

散列的最大优势就是,它只需要在数据库里面创建一个键,就可以把任意多个字段和值存储到散列表里面。相反,因为每个字符串键只能存储一个键值对,所以如果用户要使用字符串键去存储多个数据项,就只能在数据库中创建多个字符串键。

下图展示使用字符串键和散列键存储相同数据量的数据项是,数据库中创建的字符键和散列键

使用字符串键和散列键存储相同数量的数据项

从上图可以看出,为了存储4个数据项,程序须要使用4个字符串键或者一个散列键来存储。依此推算,如果须要存储100万篇文章,那么使用散列键的情况下,程序只须要在数据库中创建100万个散列键就可以了;如果使用字符串键,那么程序须要在数据库里面创建400万个字符串键。

数据库件数量增多带来的问题主要和资源有关:

  • 为了对数据库以及数据库件的使用情况进行统计,release会为每个数据库件存储一些额外的信息,并因此带来一些额外的内存消耗,对于单个数据库件来说,这些额外的内存消耗几乎可以忽略不计,但是当数据库建的数量达到上百万,上千万甚至更多的时候,这些额外的内存消耗就会变得比较可观。
  • 当散列包含的字段数量比较少的时候,radius就会使用特殊的内存优化结构去存储散列中的字段和值与字符串键相比,这种内存优化结构,存储相同数据所需的内存要少,得多,使用内存优化结构的散列越多,内存优化结构的效果也就越明显,在一定条条件下对于相同的数据使用散列键进行存储,比使用字符串键存储要节约一半以上的内存,有时候甚至会更多。
  • 除了需要消耗更多内存之外,更多的数据库键也需要占用更多的CPU,每当release需要对数据库中的键进行处理时,数据库包含的件越多,进行处理所需的CPU资源就会越多,处理所耗费的时间也会越长,典型的情况包括:统计数据库和数据库件的使用情况;对数据库执行持久化操作,或者根据持久化文件还原数据库;通过模式匹配,在数据库中查找某个键或者执行类似的查找操作。

这些操作的执行时间都会受到数据库件数量的影响。
最后除了书资源方面的优势之外,散列键还可以有效地组织起相关的多项数据,让程序产生更容易理解的数据,使得针对数据的批量操作变得更方便。
 

字符串键的优点

虽然使用散列键可以有效的节约资源并更好的组织数据,但是字符串键也有自己的优点

  • 虽然散列键命令和字符串键命令在部分功能上有重合的地方,但是字符串界命令提供的操作比散列键面料更为丰富。比如字符串能够使用setrange命令和getrange命令设置或者读取字符串值得其中一部分,或者使用命令append将新内容追加到字符串值的末尾,而散列键并不支持这些操作。

  • 对于键值对过期操作,字符串键可以在指定时间到达时自动删除指定的键。因为键过期功能针对的是整个键用户,无法为散列中的不同字段设置不同的过期时间,所以当一个散列键过期的时候,它包含的所有字段和值都将被删除。相反如果用户使用字符串键存储信息就不会遇到这样的问题,用户可以为每个字符串键分别设置不同的过期时间,让他们根据实际的需要自动被删除。

字符串键和散列键的选择

下表格从资源占用、支持的操作以及过期时间3个方面对比字符串键和散列键的优缺点

对比字符串键和散列键
比较的范畴 结果
资源占用 字符串键在数量较多的情况下,将占用大量的内存和CPU时间。相反,将多个数据项存储到同一个散列中可以有效地减少内存和CPU消耗
支持的操作 散列键支持的所有命令,几乎都有相应的字符串键版本,但字符串键支持的setrange、getrange等操作散列键不具备
过期时间 字符串键可以为每个键单独设置过期时间,独立删除某个数据项;而散列键一旦到期,它包含的所有字段和值都会被删除

既然字符串键和散列键各有优点,那么我们在构建应用程序的时候,什么时候应该使用字符串键?什么时候应该使用散列键呢?对于这个问题以下总结了一些选择的条件和方法。

  • 如果程序需要为每个数据项单独设置过期时间,那么使用字符串键。
  • 如果程序需要对数据线执行诸如setrange、getrange或者append等操作,那么优先考虑使用字符串键。当然用户也可以选择把数据存储在散列中,然后将类似的操作交给客户端执行。
  • 如果程序需要存储的数据项比较多,并且你希望尽可能的减少存储数据所需的内存,就应该优先考虑使用散列键。
  • 如果多个数据线在逻辑上属于同一组或者同一类,那么应该优先考虑使用散列键。

猜你喜欢

转载自blog.csdn.net/magi1201/article/details/113864319