`
hbi224mw
  • 浏览: 14158 次
社区版块
存档分类
最新评论

TC官方文档翻译01----TokyoCabinet简介(Tokyo Cabinet/Tokyo Tyarnt 文档系列)

阅读更多

TC官方文档翻译01----TokyoCabinet简介(Tokyo Cabinet/Tokyo Tyarnt 文档系列)
2010年06月26日
  /**  * 转载请注明出处, 由于个人技术能力有限, 英语水平欠缺,
  * 有翻译不合适或错误的地方, 请纠正, 
  * 希望不要因为我的错误误导您, 希望您的智慧可以加入.
  * @translator: selfimpr
  * @mail: lgg860911@yahoo.com.cn
  * @blog: http://blog.csdn.net/lgg201
  */ TC通过hash算法获取记录, 如果桶数组有足够多的元素, 时间复杂度就是O(1), 也就是说, 抓取一条记录需要的时间是一个常量, 而与数据库的规模无关, 这对于存储和删除是等效的.hash值的冲突通过二叉搜索树解决, 也就是说即便桶只有极少的元素, 也可以保证搜索的时间复杂度在O(logn)附近
  TC在通过加载整个桶数组到内存来改善检索. 如果桶数组在内存中, 它可能对于目标区域的访问只需要一次文件操作的路径访问, 一个保存在文件中的桶数组并不是调用'read'而是通过mmap(内存文件映射)来调用的, 因此, 数据库连接的准备时间很短, 并且两个或多个进程可以共享相同的内存映射.
  如果桶数组的元素个数大概是数据库总记录数的一半, although it depends on characteristic of the input, hash值的冲突概率约为56.7%(桶数组大小和数据库记录数相同时为36.8%, 桶数组大小为数据库记录数两倍时为21.3%, 4倍时为11.5%, 8倍时为6.0%), 在这种情况下, 对于一次检索而言, 最多会有两次文件操作. 如果把这个看作一个性能指标, 为了处理百万记录的数据库, 桶数组需要大概50万元素, 每个元素的大小是4byte(应该存储的是地址), 也就是说只要有2M的可用内存, 就可以处理100万条记录的数据存取.
  传统的DBM提供两种模式的存储操作: 'insert'和'replace', 在将要插入的key已经存在于数据库中时, 'insert'模式会保留原值不变, 'replace'模式则将该key对应的值替换为指定的新值. 除了这两种模式, TC提供了'concatenate'模式, 这种模式下, 指定的值会连接到已经存在的值的末尾并存储, 这个特性在处理向数组中增加元素时非常有用.
  TC对碎片的处理有两种方式, 一种是调用静态的优化, 把记录部署到另外一个文件, 通过一次写入清除碎片, 另外一种被称为动态优化是收集无用区域信息并用记录去替换(应该是将已经无用的区域进行记录, 在新插入大小合适的记录时, 进行重用) 尽管B+树数据库比hash数据库要慢, 它的特性是顺序访问每条记录. 次序可以由用户来指定, B+树中的记录是已排序的并且按照逻辑页进行分布.通过独立的索引维护每一页使其成为多路平衡树. 因此检索的时间复杂度是O(log n), 游标提供对记录的顺序访问. 游标可以通过指定key向前或向后跳跃到指定位置.由于每页被安排成双向链表, 因此时间复杂度为O(1).
  B+树数据库是基于上面的hash数据库实现的. 由于B+树每页的存储相当于hash数据库中的记录, B+树数据库就继承了hash数据库的存储管理效率.由于每条记录的头都比较小并且对其方式由每页大小决定, 所以在大多数情况下, 数据库文件大小是一个hash数据库的一般.尽管多个页面的操作需要更新B+树, TC通过缓存页面和缩减文件操作来加速进行处理. 在多数情况下由于所有的独立索引都缓存在内存中, 因此, 检索一条记录可能需要一次或更少的文件操作.
  B+树的每一页都是压缩存储的. 两种压缩方法: Deflate of ZLIB和Block Sorting of BZIP2都支持. 由于一页中的每条记录都有相似的规则, Lempel-Ziv或BWT算法可以提供很好的压缩效率. 在处理文本数据时, 数据库的大小缩减25%左右. 如果数据库太大或硬盘I/O造成瓶颈, 压缩特性会最大限度的提升速度. 定长数据库限制每个key必须是自然数并且值的长度是有限的, 然而, 正式由于这种这种约束定长数据库在时间和空间上的效能比其他数据结构都高.
  由于整个数据库的区域都被通过mmap(内存映射文件)映射在内存作为一个多维数组提交, 它与文件I/O性能关联非常小. 由于这种简单的结构, 定长数据库工作要快于hash数据库并且它在多线程并发的场合表现非常好.
  数据库的大小与key的范围和值的大小限制相关. 也就是说越小的key范围或越小的值长度带来的就是越小的空间占用. 比如最大key为1000000值限制大小为100bytes, 数据库大小就大约为100MB, 由于记录仅仅被加载到内存, 因此可以把数据库大小增大到虚拟内存大小. table数据库并不是直白的简单key/value结构, 而是一个类似关系型数据库的表的结构. 每条记录通过主键唯一标识并且由多个由字符串命名的列组成值. 比如, 一个"雇员号"唯一确定一个雇员, 列"name", "division", "salary"等则用来说明该雇员的其他属性. 与关系数据库的表不同的是, table数据库不需要定义任何的data schema并且可以包含与其他记录不同的结构.
  table数据库支持query进行查询, 不仅仅是主键, 而是可以通过任意的列作为条件. 查询条件由列名和条件表达式组成. 对字符串类型的列还提供了全文匹配, 向前匹配, 正则匹配等支持, 标签搜索和全文检索也被支持. 在查询中多个条件之间的逻辑交集和并集都是可用的. 通过指定升序或降序还可以对查询结果集(字符串类型或数值类型)进行排序.
  你可以在任意列创建索引用于提高搜索和排序的性能, 尽管列没有数据类型, 索引却是有类型的(只能为string和number建立). 倒排索引的空间间隔标记和字符N-gram标记也被支持. 查询优化器会在合适的时候透过每个查询使用索引, 索引的实现不同于B+树数据库的文件 数据库在文件系统上的事务机制. 一次性提交在beginning和end之间的一系列操作, 或者中断事务并回退到事务开始之前的状态. 支持两种级别的事务隔离级别: 序列化和未提交读.
  TC提供两种方式的数据库连接: "reader"和"writer". 作为一个reader能够执行检索但不能存储或删除. 作为一个writer则可以执行所有的访问操作. 通过在连接的时候进行文件锁来处理并发访问, 当一个writer连接到数据库后, 无论reader和writer都不允许连接, 当reader连接到数据库时, 只有reader可以连接. 通过这种方式可以保证在多任务并发时的数据一致性.
  TC的api提供的函数在多线程环境中都是可用的. 对无关联的数据库对象可以并行操作, 对于同一个数据库对象的操作, read-write锁被用于隔离控制. 也就是说, 当一个写线程在操作数据库的时候, 其他的读线程和写线程都是被锁定的, 然而, 当一个读线程在操作数据库的时候, 读线程是处于非锁定状态的, hash数据库和定长数据库的锁粒度是记录级的, 其他所有的数据库的锁粒度都是整个文件的锁. TC提供了一套简单的基于OO设计的api, 每种数据库操作都被封装, 公开成为一些简明的方法, 比如: 连接(open), 关闭连接(disconnect), 插入数据(put), 删除数据(out), 检索(get)等等. 由于B+树数据库, 定长数据库, hash数据库三种数据库的api是非常相似的, 所以在他们之间进行转换非常容易.此外, 抽象API提供了这些数据库的相同处理接口, 基于抽象API的应用可以在运行时决定数据库类型.
  同样提供了工具API, 比如基本的数据结构list, map等都被包含, 另外还有一些有用的特性: 内存池, 字符串处理, 编码也被包含.
  总共提供了6种C语言API, 除4种数据库对应的外, 还有工具api和抽象api.命令行接口也作为API分别提供, 这些接口对原型构建, 测试, 调试很有用. 除了C, TC还提供了Perl, Ruby, Java, Lua的api, 也希望未来有更多的第三方提供其他语言API.
  在多进程同时访问数据库或远程访问时, remote service非常有用, remote service由一个数据库服务和它的访问库组成. 应用程序可以通过远程数据库api访问数据库, 该服务实现了HTTP和部分memcached协议, 因此这类协议的产品可以很容易实现切换.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics