缘由

数据存储在MYSQ库中,数据基本维持不变,但数据量又较大(几千万)放在MYSQL中查询效率上较慢,寻求一种简单有效的方式提高查询效率,MYSQL并不擅长大规模数据量下的数据查询。

技术方案

考虑后期同样会使用到es,此次直接结合spring-boot框架形成一个独立服务,并不涉及UI展现内容,(ES版本2.4.5,5.0+版本的话就不能再使用spring data elasticsearch)技术组合如下:

Spring Boot+ Spring-data-elasticsearch + Elasticsearch

结合elasticsearch-jdbc插件,全量将数据一次性导入es中,后期不涉及数据变更。

es安装

测试期间单机安装,官网下载对应版本,由于笔者工作环境基于JDK7,所以下载5.0以下版本,5.0+均依赖Java8,同时使用到elasticsearch-jdbc插件,一并下载安装完成。

走过的大弯路

直接使用elasticsearch-jdbc工具,编写脚本文件,抽取数据到es中,脚本样例如下:

  1. #!/bin/sh
  2. DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  3. bin=${DIR}/../bin
  4. lib=${DIR}/../lib
  5. echo '
  6. {
  7.    "type": "jdbc",
  8.    "jdbc": {
  9.        "elasticsearch.autodiscover": true,
  10.        "url": "jdbc:mysql://192.168.1.3:3306/test",
  11.        "user": "root",
  12.        "password": "root",
  13.        "sql": "SELECT * from tb_name1",
  14.        "elasticsearch": {
  15.            "host": "192.168.1.1",
  16.            "port": 9300
  17.        },
  18.        "index": "my-index",
  19.        "type": "my-type"
  20.    }
  21. }
  22. ' | java \
  23.    -cp "${lib}/*" \
  24.    -Dlog4j.configurationFile=${bin}/log4j2.xml \
  25.    org.xbib.tools.Runner \
  26.    org.xbib.tools.JDBCImporter

数据导入成功后,可使用head插件直接查看到。使用基本查询测试,查询条件是name=测试&num=100,使用精确匹配term语句,查询数据未果,实际使用num=100独立查询时,有相关数据。

问题跟踪解决

导致此现象的原因在于中文分词的问题,使用elasticsearch-jdbc脚本中并未处理列的mapping类型。(中间做过一次尝试,在脚本中定义对应的type_mapping,但并未成功,有兴趣的朋友可再做尝试)。

注:es与ik分词插件结合,版本匹配需要特别关注,但本案例并不涉及

结合此案例,查询时并不需要分词,而是精确匹配,但es默认情况下是指定string类型的分词,所以在index创建之前我们需要手动指定相关列不需要分词:not_analyzed,形如:

  1. CURL -XPOST http://192.168.1.105:9200/my-index -d {
  2.    {
  3.    "mappings": {
  4.        "my-type": {
  5.            "properties": {
  6.                "name": {
  7.                    "type": "string",
  8.                    "index": "not_analyzed"
  9.                },
  10.                "num": {
  11.                    "type": "string",
  12.                    "index": "not_analyzed"
  13.                }
  14.            }
  15.        }
  16.    }
  17. }

创建索引成功后,再使用elasticsearch-jdbc的脚本导入数据,相关数据列不会再使用分词分析,再使用term组合精确查询时,就可以查询相关数据来。

SpringBoot应用

pom.xml关键配置

  1. <dependency>
  2.    <groupId>org.springframework.boot</groupId>
  3.    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>
  5. <dependency>
  6.    <groupId>org.springframework.boot</groupId>
  7.    <artifactId>spring-boot-starter-web</artifactId>
  8.    <exclusions>
  9.        <exclusion>
  10.            <artifactId>log4j-over-slf4j</artifactId>
  11.            <groupId>org.slf4j</groupId>
  12.        </exclusion>
  13.    </exclusions>
  14. </dependency>
  15. <dependency>
  16.    <groupId>org.springframework.boot</groupId>
  17.    <artifactId>spring-boot-starter</artifactId>
  18.    <exclusions>
  19.        <exclusion>
  20.            <groupId>org.springframework.boot</groupId>
  21.            <artifactId>spring-boot-starter-logging</artifactId>
  22.        </exclusion>
  23.    </exclusions>
  24. </dependency>
  25. <dependency>
  26.    <groupId>org.springframework.boot</groupId>
  27.    <artifactId>spring-boot-starter-test</artifactId>
  28.    <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31.    <groupId>org.springframework.boot</groupId>
  32.    <artifactId>spring-boot-starter-log4j</artifactId>
  33.    <version>1.3.1.RELEASE</version>
  34. </dependency>

与elasticsearch交互实体

  1. @Data
  2. @Document(indexName = "my-index", type = "my-type", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")
  3. public class DataBean {
  4.    /**
  5.     * code:名称
  6.     *
  7.     * @since JDK 1.6
  8.     */
  9.    public String name;
  10.    /**
  11.     * msg:编号
  12.     *
  13.     * @since JDK 1.6
  14.     */
  15.    public String num;
  16. }

与es交互接口类,返回数据的唯一_id值,若查得数据表示命中数据,若为空并未数据不存在

  1. public interface DataBeanRepository extends ElasticsearchRepository<DataBean, Long> {
  2.    //案例中并未使用,但可以用
  3.    public List<BlackGreyData> findByNameAndNum(String name, String num);
  4. }

下面是业务处理层,采用BoolQueryBuilder构建查询条件,也即可基于DSL模块查询数据,还可以采用Criteria查询。

  1. @Autowired
  2.    DataBeanRepository repository;
  3.    @Override
  4.    public List<DataBean> query(String name, String num, String type) {
  5.        //采用过滤器的形式,提高查询效率
  6.        BoolQueryBuilder builder = QueryBuilders.boolQuery();
  7.        builder.must(QueryBuilders.termQuery("name", name)).must(QueryBuilders.termQuery("num", num));
  8.        Iterable<DataBean> lists = repository.search(builder);
  9.        List<DataBean> datas = new ArrayList<>();
  10.        for (DataBean dataBean : lists) {
  11.            datas.add(dataBean);
  12.            logger.info("---------------------->>>Request result = 【" + dataBean + "】");
  13.        }
  14.        return datas;
  15.    }

其它再编写对应的请求响应逻辑,即可完成简单服务的完成。

测试结果

GPS数据量5000W+,精确匹配查询出来50条数据,耗时700ms左右,结果查询缓存机制,基本可以稳定在300ms左右。这也是在单节点,未作任何优化的情况的结果。

源码地址

https://github.com/backkoms/spring-boot-elasticsearch

扩展阅读:

Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析的更多相关文章

  1. Spring Boot + Elasticsearch 实现索引批量写入

    在使用Eleasticsearch进行索引维护的过程中,如果你的应用场景需要频繁的大批量的索引写入,再使用上篇中提到的维护方法的话显然效率是低下的,此时推荐使用bulkIndex来提升效率.批写入数据 ...

  2. Spring Boot + Elasticsearch 实现索引的日常维护

    全文检索的应用越来越广泛,几乎成了互联网应用的标配,商品搜索.日志分析.历史数据归档等等,各种场景都会涉及到大批量的数据,在全文检索方面,方案无外乎Lucene.Solr.Elasticsearch三 ...

  3. Spring Boot + Elasticsearch

    spring data elasticsearch elasticsearch 2.0.0.RELEASE 2.2.0 1.4.0.M1 1.7.3 1.3.0.RELEASE 1.5.2 1.2.0 ...

  4. 解决Spring boot中读取属性配置文件出现中文乱码的问题

    问题描述: 在配置文件application.properties中写了 server.port=8081 server.servlet.context-path=/boy name=张三 age=2 ...

  5. 搭建spring boot+elasticsearch+activemq服务

    目前时间是:2017-01-24 本文不涉及activemq的安装 需求 activemq实时传递数据至服务 elasticsearch做索引 对外开放查询接口 完成全文检索 环境 jdk:1.8 s ...

  6. Spring Boot Document Part II(下)

    Part II. Getting started 11. 开发第一个Spirng Boot Application使用Spring Boot的关键特征开发一个基于JAVA Web的“Hello Wor ...

  7. spring boot web项目在IDEA下热部署解决办法(四步搞定)

    最近在用spring boot 做一个web站点,修改了类.html.js等,刷新页面,没有生效,非要手动去make一下或者重启,大大降低了开发效率. 什么是热部署? 应用启动后会把编译好的Class ...

  8. spring boot 在jdk 1.7下使用 commandLineRunner

    在spring boot 中有一段代码,使用的是java 1.8的语法: @Bean public CommandLineRunner commandLineRunner(ApplicationCon ...

  9. Spring Boot 2.2.2.RELEASE 版本中文参考文档【3.1】

    使用Spring Boot 本节将详细介绍如何使用Spring Boot.它涵盖了诸如构建系统,自动配置以及如何运行应用程序之类的主题.我们还将介绍一些Spring Boot最佳实践.尽管Spring ...

随机推荐

  1. 怎样解决python dataframe loc,iloc循环处理速度很慢的问题

    怎样解决python dataframe loc,iloc循环处理速度很慢的问题 1.问题说明 最近用DataFrame做大数据 处理,发现处理速度特别慢,追究原因,发现是循环处理时,loc,iloc ...

  2. SQLServer 订阅过期解决方法

    原文:SQLServer 订阅过期解决方法 由于分发数据库执行一个较长的事务,达到了系统预定的72小时,导致了该订阅过期,数据库分发代理已不可再启用,提示错误如下: 错误信息:已将此(这些)订阅标记为 ...

  3. 财富500强的前10个公司里有8个公司在使用Qt(Qt自己认为的优点是:直觉主义、跨平台、节省时间),以及一些商业案例

    8 of Top 10 Fortune 500 use Qt Qt is the software development framework of choice by engineers in ov ...

  4. 给文件右击菜单增加7-ZIP浏览功能(用注册表设置Shell调用预览命令)

    疯狂delphi delphiXE7.XE8.XE10公开课A 群号:58592705 QQ:513187410 朱建强 BAT-给文件右击菜单增加7-ZIP浏览功能 Reg给文件右击菜单增加7-ZI ...

  5. 数据库连接池之_Druid简单使用

    数据库连接池: 连接池是创建和管理一个连接的缓冲池的技术,这些连接真备好被任何需要他们的线程使用,可以对传统的JDBCjava数据库连接()进行优化 在实际开发中,我们需要频繁的操作数据库,这就意味着 ...

  6. C#字符串类型

    C#字符串类型(string)是一种引用类型,是System.String的别名,表示Unicode字符串. 两种表示方法: 1.“C#” 直接用双引号括起来. 2.使用@,@“c:\test”,可以 ...

  7. win32内存调用图

    https://msdn.microsoft.com/en-us/library/ms810603.aspxhttps://www.codeproject.com/Articles/14525/Hea ...

  8. 全面解析ECMAScript 6模块系统

    快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中.   <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...

  9. Qt DLL总结【二】-创建及调用QT的 DLL(三篇)good

    目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS20 ...

  10. 【Windows Universal Platform】只是学习笔记 - 开始

    我是初学,之前没有windows/windows phone的应用开发经验:开博的目的只是记录和督促自己学习. 心血来潮也好,或是个人喜好的原因,想学着自己开发APP了(PS:以前做过web 开发) ...