博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mysql转ElasticSearch的分析 及JAVA API 初探
阅读量:4612 次
发布时间:2019-06-09

本文共 3753 字,大约阅读时间需要 12 分钟。

前言

最近工作中在进行一些技术优化,为了减少对数据库的压力,对于只读操作,在程序与db之间加了一层-ElasticSearch。具体实现是db与es通过bin-log进行同步,保证数据一致性,代码调用es查询数据,与mysql解耦。

优势:

  • 减少与mysql的耦合,查询不依赖于mysql特性。因为当前ElasticSearch的势头如同json一样,轻量、简洁。
  • ElasticSearch扩展性强,可以使用廉价机器平行扩展性能。
  • ElasticSearch对所有字段进行了索引,不用在原mysql表中大量添加索引,减少了数据复杂度。

API的个人理解

由于es的java api文档不多,因此参照es官方文档的概念,自己总结了一些api的用法,个人看法,不保证正确。

  1. term 和 terms 是包含操作,而不是相等操作,假如真的需要完全匹配这种行为,最好是通过添加另一个字段来实现。
  2. 在 bool 条件中过滤器的顺序对性能有很大的影响。更详细的过滤条件应该被放置在其他过滤器之前,以便在更早的排除更多的文档。
  3. 由于es有打分功能,所以api是有配合条件的。withFilter->filter->term,terms,range等一系列不打分的聚合条件。withQuery->must->matchPhrase
  4. 查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。《官方文档.p.133》(因此在进行mysql迁移时,优先使用filter)

迁移案例分析

实体

@Document(indexName = "dbName", type = "tableName", shards = 6)public class UserInfo{ /** * 主键 */ @JsonProperty("id") private Long id; /** * 用户编号 */ @JsonProperty("user_id") private String userId; /** * 分数 */ @JsonProperty("score") private String score; /** * 创建时间 */ @JsonProperty("order_time") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime;

 

  • queryOne
select * from user_info where id = #{id}

 

public UserInfo getById(String id){    CriteriaQuery query = new CriteraQuery(Criteria.where("id").is(id));    UserInfo userInfo = elasticsearchTemplate.queryForObject(query, UserInfo.class);}
  • queryForList(小数据量)
select * from user_info where user_id in #{userIdList}

 

public List
getByUserIdList(List
userIdList){ SearchQuery searchQuery = new NativeSearchQueryBuilder(). withIndices(EsQueryConstant.obtainIndicesName("dbName","tableName")). withFilter(QueryBuilders.termsQuery("user_id",userIdList)). return elasticsearchTemplate.queryForList(searchQuery,UserInfo.class); }
  • queryForList(大数据量)
select * from user_info where crete_time > #{createTime}

 

public List
getByUserIdList(Date createTime){BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().filter(QueryBuilders.rangeQuery("create_time").gt(new DateTime(createTime).toString("yyyy-MM-dd HH:mm:ss"))); SearchQuery searchQuery = new NativeSearchQueryBuilder(). withIndices(EsQueryConstant.obtainIndicesName("dbName","tableName")). withFilter(boolQueryBuilder ).build(); String scrollId = elasticsearchTemplate.scan(searchQuery, TimeValue.timeValueMinutes(20).getMillis(), false); List
result= Lists.newArrayList(); while (true) { Page
userInfoPage = elasticsearchTemplate.scroll(scrollId, TimeValue.timeValueMinutes(20).getMillis(), UserInfo.class); List
userInfoContent= orderEsPage.getContent(); if (CollectionUtils.isEmpty(userInfoContent)) { break; } result.addAll(userInfoContent); } return result; }

由于es采用的是分布式存储,所以在数据量大到一定程度的情况下,分页已经变得不可行。比如要拿1000-1010的数据,假设es有6个分片,则每个分片都要拿到1010条数据,总体排序以后取到1000-1010的数据。这样的计算显然是不可能的。所以如果数据量够大,应当使用游标的方式查询数据。虽然指定了页大小,但是这只针对于每一片,实际得到的数据不超过片数*页大小。一直循环,直到所有分片都没有满足条件的数据为止。

  • queryForPage
select * from user_info where score != #{
score} limit #{
pageIndex},#{
pageSize}
public Page
getByUserIdList(String score,int pageIndex,int pageSize){BoolQueryBuilder query= QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("score", score); SearchQuery searchQuery = new NativeSearchQueryBuilder(). withIndices(EsQueryConstant.obtainIndicesName("dbName","tableName")). withPageable(new PageRequest(pageIndex, pageSize)). withFilter(query).build(); return elasticsearchTemplate.queryForPage(searchQuery,UserInfo.class); }

后记

本文简单的介绍了mysql转ElasticSearch时的一些场景的案例,API并不难,只是相关资料少,很多功能只能探索前进,以后用到了更深入的功能会继续更新。

转载于:https://www.cnblogs.com/snake23/p/9414570.html

你可能感兴趣的文章
使用线程模拟死锁情形
查看>>
运维工程师面试题1
查看>>
JavaSpring
查看>>
How to only capute sub-matched character by grep
查看>>
js之原型
查看>>
Vue中的scoped及穿透方法
查看>>
python
查看>>
强制类型转换
查看>>
bzoj1101:[POI2007]ZAP-Queries
查看>>
canvas.drawBitmap(bitmap, src, dst, paint)
查看>>
springboot&&springcloud知识点
查看>>
SON用法简介
查看>>
ffmpeg示例一:源码
查看>>
51Nod 1042 数字0-9的数量 数位DP
查看>>
jquery隔行变色代码
查看>>
python全栈学习--day33(网络编程-socket)
查看>>
python全栈学习--day14(列表推导式,生成器表达式,内置函数)
查看>>
201771010125王瑜《面向对象程序设计(java)》第十七周学习总结
查看>>
游标cursor
查看>>
JSON 和 json 的方法
查看>>