狠狠撸

狠狠撸Share a Scribd company logo
Xapian 搜索引擎 潘俊勇 易度  everydo.com
我使用 ZODB Z – Object Database 和 Python 语言绑定的对象数据库 来自 ( 落魄少爱的 )zope 社区 开发非常快速方便! 我们的易度云办公基于这个
ZODB 的索引问题 ZODB 没有内置的索引 …
需要独立的搜索模块 不仅仅是全文索引 需要数据库的各种复杂搜索 而且要高性能 多条件 排序 COUNT 统计 支持多值字段查询 比如 tag
可选的产物 继续用 MySQL lucene  ?  solr Xapian SphinxSearch
Mysql fulltext 索引性能不佳、功能不强 多值属性 ( 比如 tag) 很难做索引 每次查询的时候,只能利用一个索引 组合查询,需要建立很多多列索引 太多索引导致索引膨胀,性能降低
lucene /Solar Java 开发的老牌搜索引擎和服务 我 不喜欢 java ,所以不感冒 不很了解 好些从 Lucene 社区跑到 xapian 说 Lucene 的可扩展性不强 数据量大就撑不住 性能一般 ( 传 Sphnix 比他快 2-4 倍 )
Xapian 使用 C++ 开发 del.icio.us (1 亿书签 ) Gmane (9 千万条消息 ) Douban 类搜索引擎的简单服务
Xapian performance 非常好 5 亿网页, 1.5T 数据库文件 小于 1S Gmane : 9 千万邮件,单服务器
sphinx 最大: boardreader.com   论坛搜索引擎, 20 亿份文档 (50 亿 ?) , 2TB(6TB?) 最忙 :  craigslist.org ,    免费的分类广告站点 ( 美国的 top10),  每天 5 千万请求   各种复杂的应用
简单比较 Xapian 25 年历史 C++ 嵌入式 写慢但读很快 无统计功能 利用磁盘存储结构 适合构建搜索引擎 Sphinx 起步 2003 年 C++ 服务器 和 mysql 整合好 提供 SQL API 索引推荐在内存中 适合更复杂应用
我们选择 xapian 用 xapian 的时候, Sphinx 还很弱 Sphinx 对我们还是不适合 索引建立靠配置文件,不方便 Sphinx 的 attribute 全部在内存里面 Xapian 更简单可控 嵌入式,而启动服务器 代码量也不大 总体结构也比较简单
搜索服务 索引 数据库 索引  Index 搜索 Search 关系数据库 文件 NoSQL 数据库 Web 应用 各种数据源 异步、实时
Xapian 特性 Ranked probabilistic search  重要词汇 Relevance feedback  相关的文档 Phrase and proximity searching  Full range of structured boolean search operators ("stock NOT market", etc)  stemming of search terms  近似词 Wildcard  任意匹配 (xap*) Synonyms  同义词 Facet search 分面搜索
Xapian 术语 Document  , document id :  一个整数 没有字段! terms   带位置信息的词或者短语,文本搜索 values   短的 字符串 ,用于 二进制 范围搜索和排序 document data  用于返回显示的任何数据,不能搜索
首先在 Terms 里面找 documents 限定范围 完了,查相应的 value ,进行排序 如果数据量大, 这个过程可能比较慢。 如果需要,可把 data 再取出 所以技巧是,尽量减少第一步的 搜索结果量 另外, Sphinx 也是这个原理。只是 他为了提高性能,把 value 全部放入 内存了。
Database 存储信息 必须 Posting list  table 每个 term  包含的 document Record table document 关联的 data Term list table 每个 document 包括的所有 term 可选 position list table  每个 term 出现的位置 value table?  主要用于保存、排序等 Spelling table  拼写纠正 synonym table  同义字典
Xapian-backend 存储格式 chert : 1.2  数据库更小,但搜索更快 flint  : 1.0 Brass  :更好的支持 replication ( 开发中 ) Remote :远端的数据库
Xapian 的 python 接口 Xapian: swig 自动生成的接口 底层,功能强,但使用不方便 Xappy :高层的封装 对多字段场景,使用更简单 太自动化,反而乱来 不是很成熟,跟不上 xapian 的变化 理解原理即可,不推荐使用
建立索引 Import xapian database = xapian.WritableDatabase('test/', xapian.DB_CREATE_OR_OPEN)  doc = xapian.Document()  doc.set_data(“ 我们爱祖国” )  doc.add_posting(“ 我们” , 1)  doc.add_posting(“ 爱” , 3)  doc.add_posting(“ 祖国” , 4)  doc.add_value(0, “20111130”) doc.add_value(1, “ 潘俊勇” ) #  添加并写入数据库 database.add_document(doc)  database.commit()
写入速度慢? Commit  保证修改的原子性 Atomic 大量数据写入逐一 commit 会很慢 解决方法 批量添加,成批 commit Commit 之前只是内存操作 hack 代码,不做完整性检查 多机分区索引,事后合并 Xapian-compact --multipass
并行修改? 不可以并行修改! 单写多读 这个和 sqlite 一样,嵌入式就是这个问题 会导致数据库崩溃! xapian 的 lock 机制有 bug 检查是否崩溃 xapian-check foo/termlist.DB
搜索 import xapian database = xapian.Database('test/')  enquire = xapian.Enquire(database)  terms = [“ 我们” , “ 祖国” ]  query = xapian.Query(xapian.Query.OP_OR, terms)  enquire.set_query(query)  matches = enquire.get_mset(0, 10)  count = matches.get_matches_estimated()  for  match  in  matches:  print  match[xapian.MSET_DID] print match[xapian.MSET_PERCENT] print match[xapian.MSET_DOCUMENT].get_data()
组合搜索 xapian.Query(op, query1, query2) OP_AND  OP_OR OP_AND_NOT  OP_FILTER  OP_AND_MAYBE  OP_XOR  OP_NEAR  OP_PHRASE  OP_ELITE_SET
使用 QueryParser 类 Google 搜索 paas site:everydo.com –Service 更简单! qp = xapian.QueryParser() qp.set_database(database)  query = qp.parse_query(query_string)
排序 相关性: enquire.set_sort_by_relevance()  默认是按 Rank 算法计算 BM25 可使用 BoolWeight ,采用进索引顺序,快速 配合 enquire.set_docid_order 按照其他属性排序 :  enquire.set_sort_by_value()  value 必须统一为可排序的字符串 enquire.set_sort_by_value_then_relevance()  enquire.set_sort_by_relevance_then_value()  自定义算法 地理位置排序 图片相似性排序
多索引字段? 内部只有一个索引! 使用前缀解决 Xappy 采用固定 2 个字母做字段前缀
搜索 读写不冲突 支持有限版本的 MVCC 如果写过于频繁,就出现读失效 ( 需要 reopen) 可以对数据库 rebuild 提升读性能
加大缓存提速? 没有特殊的缓存控制 全靠操作系统对硬盘读写的缓存
分库查询 索引数据量太大,如何可扩展? 更新慢 搜索慢 伸缩性小 可分拆成多个索引 按照不同栏目 不同的类型的数据 轻松支持多库搜索 Add_database
分布式搜索? 索引数据库位于远端的服务器 直接打开远端的数据库 2 种方法 Prog Xapian.database(Xapian::Remote::open("ssh", "search.example.com xapian-progsrv /var/lib/xapian/data/db1"));  服务器 xapian-tcpsrv:?--port?33333 Xapian::Database database(Xapian::Remote::open("searchserver", 33333));
备份? 很原始 停止写数据库,拷贝数据库 要么用支持快照的文件系统 (LVM) 无法增量备份
“ 压缩”数据库 Xapian 会有很多预留空间,便于快速修改 可使用 xapian-compact  进行压缩 数据库变小 搜索会更快 但修改会变慢 仅仅在很少修改的时候做这个
Replication 直接支持!
Xapian 优点 搜索速度快,支持大数据量 强大的全文搜索 内存占用少 嵌入式,简单 支持“实时”索引
Xapian 问题 错误的多写会导致数据库崩溃 ( 未来会修复 ) 多字段搜索,接口有点怪 不能统计 : Sum/Group 文档资料不够 开发维护人员少 Value 必须为字符串,更占用存储空间
结论 我们都喜欢简单的东西 Xapian 整体设计还是很精巧的 多方面因素做到了平衡

More Related Content

齿补辫颈补苍介绍

  • 1. Xapian 搜索引擎 潘俊勇 易度 everydo.com
  • 2. 我使用 ZODB Z – Object Database 和 Python 语言绑定的对象数据库 来自 ( 落魄少爱的 )zope 社区 开发非常快速方便! 我们的易度云办公基于这个
  • 3. ZODB 的索引问题 ZODB 没有内置的索引 …
  • 4. 需要独立的搜索模块 不仅仅是全文索引 需要数据库的各种复杂搜索 而且要高性能 多条件 排序 COUNT 统计 支持多值字段查询 比如 tag
  • 5. 可选的产物 继续用 MySQL lucene ? solr Xapian SphinxSearch
  • 6. Mysql fulltext 索引性能不佳、功能不强 多值属性 ( 比如 tag) 很难做索引 每次查询的时候,只能利用一个索引 组合查询,需要建立很多多列索引 太多索引导致索引膨胀,性能降低
  • 7. lucene /Solar Java 开发的老牌搜索引擎和服务 我 不喜欢 java ,所以不感冒 不很了解 好些从 Lucene 社区跑到 xapian 说 Lucene 的可扩展性不强 数据量大就撑不住 性能一般 ( 传 Sphnix 比他快 2-4 倍 )
  • 8. Xapian 使用 C++ 开发 del.icio.us (1 亿书签 ) Gmane (9 千万条消息 ) Douban 类搜索引擎的简单服务
  • 9. Xapian performance 非常好 5 亿网页, 1.5T 数据库文件 小于 1S Gmane : 9 千万邮件,单服务器
  • 10. sphinx 最大: boardreader.com 论坛搜索引擎, 20 亿份文档 (50 亿 ?) , 2TB(6TB?) 最忙 : craigslist.org , 免费的分类广告站点 ( 美国的 top10), 每天 5 千万请求 各种复杂的应用
  • 11. 简单比较 Xapian 25 年历史 C++ 嵌入式 写慢但读很快 无统计功能 利用磁盘存储结构 适合构建搜索引擎 Sphinx 起步 2003 年 C++ 服务器 和 mysql 整合好 提供 SQL API 索引推荐在内存中 适合更复杂应用
  • 12. 我们选择 xapian 用 xapian 的时候, Sphinx 还很弱 Sphinx 对我们还是不适合 索引建立靠配置文件,不方便 Sphinx 的 attribute 全部在内存里面 Xapian 更简单可控 嵌入式,而启动服务器 代码量也不大 总体结构也比较简单
  • 13. 搜索服务 索引 数据库 索引 Index 搜索 Search 关系数据库 文件 NoSQL 数据库 Web 应用 各种数据源 异步、实时
  • 14. Xapian 特性 Ranked probabilistic search 重要词汇 Relevance feedback 相关的文档 Phrase and proximity searching Full range of structured boolean search operators ("stock NOT market", etc) stemming of search terms 近似词 Wildcard 任意匹配 (xap*) Synonyms 同义词 Facet search 分面搜索
  • 15. Xapian 术语 Document , document id : 一个整数 没有字段! terms 带位置信息的词或者短语,文本搜索 values 短的 字符串 ,用于 二进制 范围搜索和排序 document data 用于返回显示的任何数据,不能搜索
  • 16. 首先在 Terms 里面找 documents 限定范围 完了,查相应的 value ,进行排序 如果数据量大, 这个过程可能比较慢。 如果需要,可把 data 再取出 所以技巧是,尽量减少第一步的 搜索结果量 另外, Sphinx 也是这个原理。只是 他为了提高性能,把 value 全部放入 内存了。
  • 17. Database 存储信息 必须 Posting list table 每个 term 包含的 document Record table document 关联的 data Term list table 每个 document 包括的所有 term 可选 position list table 每个 term 出现的位置 value table? 主要用于保存、排序等 Spelling table 拼写纠正 synonym table 同义字典
  • 18. Xapian-backend 存储格式 chert : 1.2 数据库更小,但搜索更快 flint : 1.0 Brass :更好的支持 replication ( 开发中 ) Remote :远端的数据库
  • 19. Xapian 的 python 接口 Xapian: swig 自动生成的接口 底层,功能强,但使用不方便 Xappy :高层的封装 对多字段场景,使用更简单 太自动化,反而乱来 不是很成熟,跟不上 xapian 的变化 理解原理即可,不推荐使用
  • 20. 建立索引 Import xapian database = xapian.WritableDatabase('test/', xapian.DB_CREATE_OR_OPEN) doc = xapian.Document() doc.set_data(“ 我们爱祖国” ) doc.add_posting(“ 我们” , 1) doc.add_posting(“ 爱” , 3) doc.add_posting(“ 祖国” , 4) doc.add_value(0, “20111130”) doc.add_value(1, “ 潘俊勇” ) # 添加并写入数据库 database.add_document(doc) database.commit()
  • 21. 写入速度慢? Commit 保证修改的原子性 Atomic 大量数据写入逐一 commit 会很慢 解决方法 批量添加,成批 commit Commit 之前只是内存操作 hack 代码,不做完整性检查 多机分区索引,事后合并 Xapian-compact --multipass
  • 22. 并行修改? 不可以并行修改! 单写多读 这个和 sqlite 一样,嵌入式就是这个问题 会导致数据库崩溃! xapian 的 lock 机制有 bug 检查是否崩溃 xapian-check foo/termlist.DB
  • 23. 搜索 import xapian database = xapian.Database('test/') enquire = xapian.Enquire(database) terms = [“ 我们” , “ 祖国” ] query = xapian.Query(xapian.Query.OP_OR, terms) enquire.set_query(query) matches = enquire.get_mset(0, 10) count = matches.get_matches_estimated() for match in matches: print match[xapian.MSET_DID] print match[xapian.MSET_PERCENT] print match[xapian.MSET_DOCUMENT].get_data()
  • 24. 组合搜索 xapian.Query(op, query1, query2) OP_AND OP_OR OP_AND_NOT OP_FILTER OP_AND_MAYBE OP_XOR OP_NEAR OP_PHRASE OP_ELITE_SET
  • 25. 使用 QueryParser 类 Google 搜索 paas site:everydo.com –Service 更简单! qp = xapian.QueryParser() qp.set_database(database) query = qp.parse_query(query_string)
  • 26. 排序 相关性: enquire.set_sort_by_relevance() 默认是按 Rank 算法计算 BM25 可使用 BoolWeight ,采用进索引顺序,快速 配合 enquire.set_docid_order 按照其他属性排序 : enquire.set_sort_by_value() value 必须统一为可排序的字符串 enquire.set_sort_by_value_then_relevance() enquire.set_sort_by_relevance_then_value() 自定义算法 地理位置排序 图片相似性排序
  • 27. 多索引字段? 内部只有一个索引! 使用前缀解决 Xappy 采用固定 2 个字母做字段前缀
  • 28. 搜索 读写不冲突 支持有限版本的 MVCC 如果写过于频繁,就出现读失效 ( 需要 reopen) 可以对数据库 rebuild 提升读性能
  • 30. 分库查询 索引数据量太大,如何可扩展? 更新慢 搜索慢 伸缩性小 可分拆成多个索引 按照不同栏目 不同的类型的数据 轻松支持多库搜索 Add_database
  • 31. 分布式搜索? 索引数据库位于远端的服务器 直接打开远端的数据库 2 种方法 Prog Xapian.database(Xapian::Remote::open("ssh", "search.example.com xapian-progsrv /var/lib/xapian/data/db1")); 服务器 xapian-tcpsrv:?--port?33333 Xapian::Database database(Xapian::Remote::open("searchserver", 33333));
  • 32. 备份? 很原始 停止写数据库,拷贝数据库 要么用支持快照的文件系统 (LVM) 无法增量备份
  • 33. “ 压缩”数据库 Xapian 会有很多预留空间,便于快速修改 可使用 xapian-compact 进行压缩 数据库变小 搜索会更快 但修改会变慢 仅仅在很少修改的时候做这个
  • 35. Xapian 优点 搜索速度快,支持大数据量 强大的全文搜索 内存占用少 嵌入式,简单 支持“实时”索引
  • 36. Xapian 问题 错误的多写会导致数据库崩溃 ( 未来会修复 ) 多字段搜索,接口有点怪 不能统计 : Sum/Group 文档资料不够 开发维护人员少 Value 必须为字符串,更占用存储空间
  • 37. 结论 我们都喜欢简单的东西 Xapian 整体设计还是很精巧的 多方面因素做到了平衡