TairSearch:加速多列索引查询

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 互联网及传统行业应用服务的关键数据一般存储在MySQL这类的关系型数据库中。如需缓解数据库访问压力,可引入Redis等缓存系统承担热数据的查询,以此提升查询效能。然而业务场景如果是在数据库上做随意多列组合索引查询或者like模糊匹配查询,使用普通的KV缓存系统并不能完全承载住,往往需要引入lua或者外部计算等额外的联合查询匹配过滤机制。TairSearch是一个实时全内存检索服务,其核心的倒排索引

互联网及传统行业应用服务的关键数据一般存储在MySQL这类的关系型数据库中。如需缓解数据库访问压力,可引入Redis等缓存系统承担热数据的查询,以此提升查询效能。然而业务场景如果是在数据库上做随意多列组合索引查询或者like模糊匹配查询,使用普通的KV缓存系统并不能完全承载住,往往需要引入lua或者外部计算等额外的联合查询匹配过滤机制。TairSearch是一个实时全内存检索服务,其核心的倒排索引机制既能满足词根的模糊匹配查询,且可作为热数据存算一体加速任意多列组合索引的联合查询效率。本文将阐述TairSearch如何支持以上场景。

KV缓存在多列灵活查询场景的局限性

设计关系型数据库表时,除可设置主键索引,还可以设置多个二级索引,以及多种联合索引。
使用KV缓存服务时,以Redis为例,一般使用Hash结构映射关系型数据库字段。
将数据库表中的行记录导入到Redis的Hash结构中,以行中主键字段的值作为Redis hash的key,其他字段名作为hash的field,行字段的值作为hash的value。如果查询场景只涉及主键索引,在Redis中可以直接通过hmget的方式获取到行中指定字段的信息。但在以下场景中则有明显的局限性:

  1. 查询涉及二级索引,Redis中并不支持按hash中的field内容来查询,只能通过在Redis中再用Hash存储关系型数据库中的二级索引。不仅增加导入行数据的复杂程度,也因为冗余数据造成内存空间的膨胀。
  2. 查询涉及联合索引,Redis中并不支持对Hash类型的多key联合查询,用户侧只能在外部或者lua脚本中实现联合查询过滤规则,涉及到了数据的读取和挪动。

下文以支撑流量洪峰时期的机票搜索服务为例,讲述如何使用TairSearch加速任意多列组合索引的联合查询效率。

使用TairSearch加速多列组合索引的联合查询

以某机票搜索界面为模板,可以看到精准搜索机票涉及到几个关键条件:出发地、目的地、日期、经济/公务/头等舱、带儿童、带婴儿。查询结果带有多个航班信息。在暑期、国庆、春节等中长假期时间内,对热门旅游度假区的航班查询容易造成流量洪峰。

TairSearch如何支持这类的热门航旅查询需求?
TairSearch中存储所有待飞的航班信息,已航班的出发地departure 、 目的地destination 拼接作为keydeparture_destination 。因为航班中多个出发地_目的地在搜索航班中并无关联关系,所以key是相互独立的,可直接使用Tair分布式的集群架构存储,进一步提升并行查询能力。
出发地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"
            }
        }
    }
}'

将航班信息按照以上字段整理成文档写入到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
}'

搜索头等舱的航班且按照航班的出发时间排序:

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

使用带use_cache的方式访问可以开启query cache的功能,query_cache的有效期是10s,可以对热点航班自带查询结果的热点缓存功能。
模拟随机写入10天内zhuhai_hangzhou有80个航班,且每个航班有6种配置的价格,压测查询的性能数据:

redis-benchmark -r 1 -n 500000 tft.search zhuhai_hangzhou '{"sort":["departure_time"], "query":{"bool":{"must":[{"term":{"date":"2022-09-01"}},{"term":{"seat":"first"}}]}}}'
100.00% <= 3 milliseconds
20592.23 requests per second

开启query_cache:

redis-benchmark -r 1 -n 500000 tft.search zhuhai_hangzhou '{"sort":["departure_time"], "query":{"bool":{"must":[{"term":{"date":"2022-09-01"}},{"term":{"seat":"first"}}]}}}' use_cache
100.00% <= 2 milliseconds
58920.57 requests per second

结语

TairSearch集缓存与计算于一体的全内存实时全文检索系统,可加速传统关系型数据多列组合查询效率。欢迎大家使用TairSearch产品,任何产品意见和更多的场景需求均可反馈给我们,TairSearch产品技术服务仍在持续迭代完善,期待您的参与。附TairSearch API文档

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
索引
15. 索引是越多越好嘛? 什么样的字段需要建索引, 什么样的字段不需要 ?
是否越多索引越好?并非如此。应根据需求建索引:主键自动索引,频繁查询、关联查询、排序、查找及统计分组字段建议建索引。但表记录少,频繁增删改操作,频繁更新的字段,以及使用频率不高的查询条件则不需要建索引。
110 0
|
10天前
|
数据库 索引
联合索引和单独列索引哪个更好
【10月更文挑战第15天】联合索引和单独列索引哪个更好
35 2
|
5月前
|
SQL 关系型数据库 MySQL
MySQL数据库——索引(6)-索引使用(覆盖索引与回表查询,前缀索引,单列索引与联合索引 )、索引设计原则、索引总结
MySQL数据库——索引(6)-索引使用(覆盖索引与回表查询,前缀索引,单列索引与联合索引 )、索引设计原则、索引总结
88 1
|
索引
索引是越多越好嘛? 什么样的字段需要建索引, 什么样的字段不需要 ?
索引是越多越好嘛? 什么样的字段需要建索引, 什么样的字段不需要 ?
130 0
|
数据库 索引
索引是越多越好嘛? 什么样的字段需要建索引
索引的作用是加快数据库的查询速度,但并不是索引越多越好。过多的索引会增加数据库的存储空间和维护成本,并且在写操作时可能会降低性能。
224 0
|
存储 SQL 关系型数据库
【名词解释与区分】聚集索引、非聚集索引、主键索引、唯一索引、普通索引、前缀索引、单列索引、组合索引、全文索引、覆盖索引
【名词解释与区分】聚集索引、非聚集索引、主键索引、唯一索引、普通索引、前缀索引、单列索引、组合索引、全文索引、覆盖索引
371 1
【名词解释与区分】聚集索引、非聚集索引、主键索引、唯一索引、普通索引、前缀索引、单列索引、组合索引、全文索引、覆盖索引
|
存储 SQL 关系型数据库
|
存储 关系型数据库 MySQL
MySQL中什么是什么是主键索引、联合索引、覆盖索引、索引条件下推及区别
主键索引:它是一种特殊的唯一索引,不允许有空值,一般在建表的时候指定主键,就会创建主键索引,CREATE INDEX不能用来创建主键索引,通常使用ALTER TABLE来代替。
169 0
|
存储 SQL 关系型数据库
什么是索引覆盖?什么是索引下推?
什么是索引覆盖?什么是索引下推?
403 0
什么是索引覆盖?什么是索引下推?