随着业务发展跨表join查询需求越来越多,系统的慢查询不断报出,引入ElasticSearch 来实现聚合查询势在必行。ES是一个基于 Lucene 的搜索引擎,通过将业务主表及辅表的索引字段及需要like字段同步到ES里,每张表的索引字段最终汇总成一个联合索引,来实现多个表的跨表搜索。
性能要求
检索需求响应时间均值 20ms 以内,对于命中缓存的在 2ms 以内返回
单 Type 与多 Type(多 Index)
在ES中一个 Index 可以理解为一个库,一个 Type 可以理解为一张表,但从6.0.0 版本起已废弃:一个 Index对于多个Type(只能一对一),但考虑到有一些业务还在使用5.x版本。
| 单 Type | 多 Type(多 Index) |
优点 | 一次请求即可将目标信息全量返回; 拆分冷热隔离维护成本可控; | 可以做到索引字段与表结构一一对应(直观简单); 数据同步隔离单一; |
缺点 | 数据同步成本高一些; 数据聚合时有一致性问题; | 获取数据时候需要进行数据聚合,比如一次跨 5 张表索引联查,需要先分别取出 5 张表的数据,然后做一次交集。性能会有影响; 当数据做冷热隔离,数据拆分时候多 Type 的拆分和维护成本反而更高; |
小结,若业务场景宜满足为了性能尽可能的采用单 Type方案!
索引字段数量
由于业务主表及其扩展信息字段较多,如果将这些信息全量同步到 ES 会导致很多问题:
- 索引字段过多,索引文件也会随之变大,检索效率会受到影响
- 不需要索引的字段过多,也会导致新的io问题
so,尽可能的自定义mapping,不要存储与搜索无关的数据,而下面这个transRouteAndProducts节点(json特别大)不分词不索引仅存储也是不可取的
{
"mappings": {
"static_line": {
"properties": {
"productId": {
"type": "keyword"
},
"productType": {
"type": "keyword"
},
"startStationCode": {
"type": "integer"
},
"endStationCode": {
"type": "integer"
},
"status": {
"type": "keyword"
},
"startHubId": {
"type": "keyword"
},
"transRouteAndProducts": {
"enabled": false
}
}
}
}
}
那获取详情呢,比如获取的订单号列表到mysql各个扩展表去获取具体信息,数据组装效率低下怎么破?
一次完整的订单列表拉取时间=数据检索时间+数据组装时间,而数据组装就算是批量获取,也要去取 N(假如有 N 张订单扩展表)次,即使并行去取也不够高效!
存宽表是个不错的方案,纠结该多宽也十分讲究!
建议:一个宽表维护业务主表的基本信息及其强依赖的扩展信息。
引入 Hbase 来为详情数据组装 Hbase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。可以通过 MapReduce 来处理 HBase 中的海量数据。
此时我们可以将宽表存入至Hbase,历史数据采用 BulkLoad 导入,增量数据采用消息同步写入,以订单号为 rowKey 为订单号。
那如何保证ES和Hbase的实时性与一致性呢?
可采用Change Data Capture Solution方案,监听 binlog 然后同步到消息队列中,业务消费处理同步到 Es 和 Hbase。对报警监控的指标进行关注,失败重试补偿就即可。
建立实时性的监控指标(差值)
一个消息的处理时间:binlogTime->reviceMqTime->bunsProcessTime->addEsOrHbaseTime
如果不能保证业务消费的幂等性,那么消息的乱序,数据的重放监控补偿等等就会很被动。这里有几种幂等思路:可以参阅我的另一篇文章幂等解疑
elasticsearch是解决跨表join查询很好的手段。
标签:join,数据,type,索引,跨表,elasticsearch,Hbase,Type,ES From: https://blog.51cto.com/alex/6164857