前言

最近工作中在进行一些技术优化,为了减少对数据库的压力,对于只读操作,在程序与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. 搭建Lepus数据库监控系统-记录

    一.  安装环境 系统环境:centos6.5 IP:192.168.30.242 hostname:vpn.org 软件:LAMP均已安装.(请确保这些正常安装,并能使用). 系统核心包:(摘自官方 ...

  2. Disconf实践指南:安装篇

    Disconf是百度开源出来的一款基于Zookeeper的分布式配置管理软件.目前很多公司都在使用,包括滴滴.百度.网易.顺丰等公司.通过简单的界面操作就可以动态修改配置属性,还是很方便的.使用Dis ...

  3. day9-数据库操作与Paramiko模块

    堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接: 1 ...

  4. Django学习---cookie和session

    cookie 客户端浏览器上的一个文件,以键值对的形式存储,如{“user”:“dacehgnzi”} 入门:实现一个简单的登录功能 views.py: user_info = { '}, '}, } ...

  5. python中的socket模块

    熟悉了一下python的socket模块,感觉还是有点好玩的,不过坑也也是不少的. 1.服务器端代码 #!/usr/bin/env python import socket HOST='192.168 ...

  6. URLDownloadToFileW

    [ilink32 Error] Error: Unresolved external 'URLDownloadToFileW' referenced from D:\USERS\PUBLIC\DOCU ...

  7. Expect 小脚本

    简介: Expect 可以替系统管理员完成与系统的交互式操作 shell > yum -y install expect # 可以通过 yum 安装 shell > which expec ...

  8. python时间戳、日期、时间转换

    1.str转时间戳 # 字符类型的时间 tss1 = '2013-10-10 23:40:00' # 转为时间数组 timeArray = time.strptime(tss1, "%Y-% ...

  9. 【原】使用puppeteer爬虫下载Midi文件

    The Beatles 乐队的 Midi文件下载地址 puppeteer官方github地址 midi文件爬取示例代码github地址 1.安装npm 参考:安装npm及cnpm(Windows) 修 ...

  10. [转]NDK编译库运行时报dlopen failed: cannot locate symbol "__exidx_end" 解决办法

    原文链接:http://blog.csdn.net/acm2008/article/details/41040015 当用NDK编译的库在运行加载时报如下错: dlopen("/data/d ...