前言

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

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

API的个人理解

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

  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<UserInfo> getByUserIdList(List<String> 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<UserInfo> 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<UserInfo> result= Lists.newArrayList();
while (true) {
Page<UserInfo> userInfoPage = elasticsearchTemplate.scroll(scrollId, TimeValue.timeValueMinutes(20).getMillis(), UserInfo.class);
List<UserInfo> 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<UserInfo> 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并不难,只是相关资料少,很多功能只能探索前进,以后用到了更深入的功能会继续更新。

mysql转ElasticSearch的分析 及JAVA API 初探的更多相关文章

  1. Elasticsearch 2.3.3 JAVA api说明文档

    原文地址:https://www.blog-china.cn/template\documentHtml\1484101683485.html 翻译作者:@青山常在人不老 加入翻译:cdcnsuper ...

  2. ElasticSearch 5.0.1 java API操作

    今天来说下使用ES 5.0.1的API来进行编码. 开始之前,简单说下5.0.1跟之前的几个变化.之前的ES自身是不支持delete-by-query的,也就是通过查询来删除,可以达到批量的效果,是因 ...

  3. elasticsearch elk最全java api 搜索 聚合、嵌套查询

    目录 一. 一般查询... 2 (一) matchAllQuery(client). 2 (二) matchQuery(client);3 (三) multiMatchQuery(client);3 ...

  4. ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程

    前言 在上一篇中介绍了ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解,本篇文章就来讲解下 ElasticSearch 6.x官方Java API的 ...

  5. mysql转ElasticSearch的案例分析

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

  6. Elasticsearch java api 基本搜索部分详解

    文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...

  7. 第08章 ElasticSearch Java API

    本章内容 使用客户端对象(client object)连接到本地或远程ElasticSearch集群. 逐条或批量索引文档. 更新文档内容. 使用各种ElasticSearch支持的查询方式. 处理E ...

  8. Elasticsearch Java API 很全的整理

    Elasticsearch 的API 分为 REST Client API(http请求形式)以及 transportClient API两种.相比来说transportClient API效率更高, ...

  9. Elasticsearch java api操作(二)(Java High Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

随机推荐

  1. angualr 之 $$phase

    对于angular, $$phase 是 作为angular 内部状态表示位,用来标示当前是处于哪个阶段. 用有的阶段有 $digest $apply 在使用的是例如你想调用scope.$apply的 ...

  2. Oracle播放多条 INSERT ALL

    Oracle INSERT ALL 语句介绍 Oracle INSERT ALL 语句用来用一个 INSERT 语句添加多行.该行可以只使用一个SQL命令插入到一个表或多个表. 语法 Oracle I ...

  3. 03-23 MVC框架(以查询、删除为例)

    1.MVC的定义: MVC(Model-View-Controller,模型-视图-控制器)是用于将应用程序粉好吃呢过如下3个主要方面的体系结构模式: 模型(Model):一组类和业务规则,类用于描述 ...

  4. Android Studio 2.3.3 添加ksoap2的引用(拒绝网上其他的忽悠),也适用于添加其他Jar的引用

  5. 使用COM口的2、3针的通断作为中端源(有一个读图像的摄像头,当把卡插到位时触发中端,防止在插卡的过程中出现不稳定的图像)

    利用串口2读,串口3发数据的特点.建立不断的发送流,再从接收端接收.如果收到,则数据畅通,否则断开.相当于产生一个中断.这样电脑对外部事件可作出反应. using System;using Syste ...

  6. Embarcadero RAD Studio 2016 Product Approach and Roadmap

    delphi  2016 路线图 http://community.embarcadero.com/article/news/16211-embarcadero-rad-studio-2016-pro ...

  7. Set与List之间转化

    List list = new ArrayList(set);Set set = new HashSet(list); //但是有一点,转换当中可能要丢失数据,尤其是从list转换到set的时候,因为 ...

  8. jQuery插件–jqueryflexselect下拉框自动提示

    原理:用户在文本框中输入一个字符(或输入字符的首字母),然后利用ajax,从后台服务器中进行检索,组装后并返回到页面,页面通过javascript进行解析,在一个层里面显示出来. 类似的效果如下: & ...

  9. pl/sql中if语句的使用

  10. cdoj916-方老师的分身 III 【拓扑排序】

    http://acm.uestc.edu.cn/#/problem/show/916 方老师的分身 III Time Limit: 3000/1000MS (Java/Others)     Memo ...