基于TairSearch加速多列索引联合查询

TairSearch是集缓存与计算于一体的实时全内存检索系统,其核心的倒排索引机制既能满足词根的模糊匹配查询,也能作为热数据存储设备,实现存储计算一体化,加速任意、多列索引的联合查询效率。

背景信息

互联网及传统行业应用服务的关键数据通常存储在MySQL等关系型数据库中。为缓解数据库访问压力,通常会引入Redis等Key-value缓存系统(KV缓存系统)承担热数据的查询,以提升查询效能。然而,当业务场景需要在数据库中进行多列索引联合查询或LIKE模糊匹配查询时,普通的KV缓存系统无法较好地独立支撑以上场景,往往需要引入Lua脚本或外部计算等额外的过滤匹配机制实现联合查询。

KV缓存系统在多列索引联合查询场景的局限性

在将数据导入至KV缓存系统时,以Redis为例,通常会将关系型数据库的行数据导入至Redis的Hash结构:以行数据中主键字段的值作为Redis Hash的Key,其他字段名作为Hash的Field,其字段的值作为对应Field的Value。

如果仅涉及查询主键索引,则在Redis中可以直接通过HMGET的方式获取指定字段的信息。但在关系型数据库中,不仅可以存在主键索引,还可以设置多个二级索引以及多种联合索引等,用于提高查询效率。然而Redis在如下场景中存在明显局限性:

  • 二级索引查询:Redis不支持以Hash结构中的field内容进行查询,因此只能在Redis中创建2层Hash结构来存储关系型数据库中的二级索引。此方案不仅增加了导入数据的复杂度,也因数据冗余造成内存空间浪费。

  • 联合索引查询:Redis不支持对Hash结构进行多Key联合查询,用户只能通过Lua脚本或外部计算实现联合查询。

本文以TairSearch支撑流量洪峰时的机票搜索业务为例,介绍如何通过TairSearch,加速任意、多列索引的联合查询效率。

说明

关于TairSearch的详细介绍及命令示例,请参见Search

精准搜索机票示例

在暑期、国庆、春节等中长假期时,热门旅游度假区的航班查询容易造成流量洪峰。在该场景下,可以将所有的待飞航班信息存储至TairSearch中。

创建文档索引

精准搜索机票

以某服务平台的机票搜索界面为例,精准搜索机票涉及几个关键条件:出发地、目的地、出行日期、舱位、是否带儿童或婴儿等。

本示例以出发地、目的地拼接作为TairSearch的Key(departure_destination),例如zhuhai_hangzhou。创建如下索引字段:出发地(departure)、目的地(destination)、出行日期(date)、舱位(seat)、是否带儿童或婴儿(with)、航班号(flight_id)、价格(price)、起飞时间(departure_time)、降落时间(destination_time)。

说明

如需增加或调整字段,可直接执行TFT.UPDATEINDEX

代码示例如下:

TFT.CREATEINDEX zhuhai_hangzhou '{
    "mappings":{
        "properties":{
            "departure":{"type":"keyword"},
            "destination":{"type":"keyword"},
            "date":{"type":"keyword"},
            "seat":{"type":"keyword"},
            "with":{"type":"keyword"},
            "flight_id":{"type":"keyword"},
            "price":{"type":"double"},
            "departure_time":{"type":"long"},
            "destination_time":{"type":"long"}
        }
    }
}'

预计输出:

OK

写入数据

整理航班信息,写入TairSearch文档,代码示例如下:

TFT.ADDDOC zhuhai_hangzhou '{
    "departure":"zhuhai",
    "destination":"hangzhou",
    "date":"2022-09-01",
    "seat":"first",
    "with":"baby",
    "flight_id":"CZ1000",
    "price":986.1,
    "departure_time":1661991010,
    "destination_time":1661998210
}'

预计输出:

"{"_id":"16615908912020060"}"
# 返回文档ID,格式为JSON。

精准搜索

搜索2022年09月01日珠海至杭州,头等舱座位的航班,且按照航班的出发时间进行排序,代码示例如下。

TFT.Search zhuhai_hangzhou '{"sort":["departure_time"],"query":{"bool":{"must":[{"term":{"date":"2022-09-01"}},{"term":{"seat":"first"}}]}}}'

预计输出:

"{
    "hits": {
        "hits": [
            {
                "_id": "16615908912020060",
                "_index": "zhuhai_hangzhou",
                "_score": 0.433955,
                "_source": {
                    "departure": "zhuhai",
                    "destination": "hangzhou",
                    "date": "2022-09-01",
                    "seat": "first",
                    "with": "baby",
                    "flight_id": "CZ1000",
                    "price": 986.1,
                    "departure_time": 1661991010,
                    "destination_time": 1661998210
                }
            }
        ],
        "max_score": 0.433955,
        "total": {
            "relation": "eq",
            "value": 1
        }
    }
}"