响应速度与智能化如何平衡,携程酒店搜索实践( 四 )


2)查询过滤,比较字段和值时,使用lucene列式存储,即DocValues,而不是去获取行数据 。
3)去除CBO(基于成本的优化器) 。如果开发对执行计划了然于胸,就会发现在一些复杂场景下传统数据库中的CBO经常帮倒忙,导致我们不得不使用use index这种语法 。去除CBO的同时,用不同的语法让开发可以自定义执行计划是走索引还是走过滤,降低执行计划的不确定性,也可以降低查询编译期的耗时 。而RBO(基于规则的优化器)中的一些规则可以保留,比如任何条件和false取交集,默认就返回false,而不是真的去执行其查询 。
4.1.3 多态
搜索语言需要支持编译时的多态,提高用户友好性 。
1)函数多态,例如max函数,如果传入的是整型那么返回的也是整型,如果传入的是浮点型,返回的也是浮点型 。
2)运算符多态,例如加号"+"运算,如果两边都是数值类型,那么按数值相加,并且设计合适的隐式转换规则;如果一边是字符串,那么就把两边按字符串concat起来 。
支持更多的地理搜索功能
从语言层面支持地理搜索,而不需要编写各种语法糖 。
除了支持常用的距离范围搜索,还利用了计算图形学的算法和KD树,支持多边形内的点的搜索、点到多边形的距离搜索,用于查询多边形区域范围内以及周边的召回 。
4.1.4 安全性
搜索语言需要支持查询参数化,来避免查询脚本注入 。这一点和SQL一样,ElasticSearch也已经支持参数化的script 。我们对参数化进行了扩展,使其参数本身可以为一个表达式,在查询编译时预执行,实现类似Shell或者是JS中eval的功能 。
4.1.5 支持描述业务流程
上文中所说的在查询编译时预执行的表达式,是一种doc无关的表达式 。相比而言,查询执行时的表达式都需要传入一个docid来获取当前doc 。
上文中描述的语义分析提取核心词以后,需要通过核心词以及规则系统生成新的查询和排序 。这种doc无关的表达式,我们正可以用来支持规则系统这种和具体doc无关的业务逻辑,类似PL/SQL这种面向存储过程的语言,这也是ElasticSearch中暂未实现的功能 。
踩过的坑
上设计一门新的语言时,不要一开始就设计为词法分析和语法分析双层编译结构,也不要一开始就设计action表,因为在设计新语言的一开始可能并不清楚词法和语法的边界在哪里,即使事先明确定义,做到一半的时候可能还会再做修改 。对于语法简单的DSL,使用基于字符的递归下推自动机实现编译功能是更好的选择,对于后续的语法修改会更加灵活 。
总结搜索引擎本身对数据库事务要求不强,数据计算量比较大,是一种CPU密集型的、对响应时间敏感的信息检索系统 。一方面是用户对于其智能化的需求,一方面又是用户对于其响应速度的需求,保持两者之间的平衡一直是个难题 。
所幸业界有很多较为成熟的搜索产品:Solar/Lucene、ElasticSearch,也有很多可供借鉴的算法,还有很多或新或旧的存储,例如HBase、LevelDB、RocksDB等等 。他山之石可以攻玉,只要我们不迷信权威,充分了解这些产品或者算法背后的实现原理,就可以站在巨人的肩膀上,更加灵活地找到适合当前场景的技术方案,甚至创造出全新的算法和工具,不断提升用户的搜索体验 。
【作者简介】mczhao,携程资深软件工程师,关注自然语言处理、搜索引擎和数据库内核开发 。
更多携程技术人一手干货文章,请关注“携程技术”微信公众号 。

【响应速度与智能化如何平衡,携程酒店搜索实践】


推荐阅读