mysql转ElasticSearch的案例分析
前言
最近工作中在进行一些技术优化,为了减少对数据库的压力,对于只读操作,在程序与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官方文档
- term 和 terms 是包含操作,而不是相等操作,假如真的需要完全匹配这种行为,最好是通过添加另一个字段来实现。
- 在 bool 条件中过滤器的顺序对性能有很大的影响。更详细的过滤条件应该被放置在其他过滤器之前,以便在更早的排除更多的文档。
- 由于es有打分功能,所以api是有配合条件的。withFilter->filter->term,terms,range等一系列不打分的聚合条件。withQuery->must->matchPhrase
- 查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。《官方文档.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的案例分析的更多相关文章
- 170301、使用Spring AOP实现MySQL数据库读写分离案例分析
使用Spring AOP实现MySQL数据库读写分离案例分析 原创 2016-12-29 徐刘根 Java后端技术 一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案 ...
- 161220、使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- 使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- MySQL排序原理与案例分析
前言 排序是数据库中的一个基本功能,MySQL也不例外.用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Group by语句,Distinct ...
- [转]MySQL批量更新死锁案例分析
文章出处:http://blog.csdn.net/aesop_wubo/article/details/8286215 问题描述 在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常, ...
- [转]MySQL排序原理与案例分析
这篇文章非常好,就把他转过来 前言 排序是数据库中的一个基本功能,MySQL也不例外.用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Grou ...
- MySQL批量更新死锁案例分析--转载
问题描述 在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackE ...
- (转)MySQL排序原理与案例分析
前言 排序是数据库中的一个基本功能,MySQL也不例外.用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Group by语句,Distinct ...
- MySQL实例crash的案例分析
[作者] 王栋:携程技术保障中心数据库专家,对数据库疑难问题的排查和数据库自动化智能化运维工具的开发有强烈的兴趣. [问题描述] 我们生产环境有一组集群的多台MySQL服务器(MySQL 5.6.21 ...
随机推荐
- 三.GC相关之三分钟认识GC算法
GC算法慢慢演化,进化到了现在的分代GC.其进化过程 标记-清除算法 –> 标记-复制算法 –> 标记-整理算法 –> 分代算法. 在介绍算法之前,我们知道Java是动态加载.其特点 ...
- JUnit4总结
JUnit4使用要求: 测试方法必须使用@Test进行修饰 测试方法必须使用public void 进行修饰,不能带任何的参数 新建一个源代码目录来存放我们的测试代码 测试类的包应该和被测试类保持一致 ...
- ES6 变量、常量声明总结
较之前ES5,新颁布在声明上有改变 一.var 对比 let 1.作用域不同 let只在命令所在的代码块 {} 里有效 ES5只有全局作用域和函数作用域,没有块级作用域,带来很多不合理的场景,比如 ...
- 如何免费使用jrebel 和eclipse 项目配合完成热部署功能
天,感谢王同学分享了热部署插件,jrebel,说修改后台代码可以不用重启tomcat,于是立即下载使用....本来很简单的一个事情,因为参照了网上各种帖子,结果坑的不行....所以把自己的经验分享一下 ...
- python 排序sorted
num = [3,2,4,6,5] anum = sorted(num) dnum = sorted(num,reverse=True) print '升序:',anum # 升序: [2, 3, 4 ...
- akoj-1369 贪吃蛇
贪吃蛇 Time Limit:1000MS Memory Limit:65536K Total Submit:9 Accepted:2 Description 有童年的孩子都玩过这个经典游戏,不过这里 ...
- PXE+kickstart无人值守安装CentOS 6
本文目录: 1.1 PXE说明 1.2 PXE流程 1.3 部署环境说明 1.4 部署DHCP 1.5 部署TFTP 1.6 提供pxe的bootloader和相关配置文件 1.7 利用原版安装镜像获 ...
- go的变量redeclare的问题,golang的一个小坑
go的变量声明有几种方式: 1 通过关键字 var 进行声明 例如:var i int 然后进行赋值操作 i = 5 2 最简单的,通过符号 := 进行声明和赋值 例如: i:=5 golang会 ...
- chrome地址栏命令
Chrome作为一个前端开发的标准浏览器,用来体验和测试日新月异的新特性,自然是没话说. 有些新特性是需要特意开启设置的,有很多浏览器的内置功能也是要通过命令来开启或者使用的. Chrome 有很多的 ...
- VBS windows监控
http://bbs.csdn.net/topics/230078112'/************************************************************** ...