首页 文章 精选 留言 我的

精选列表

搜索[es],共3892篇文章
优秀的个人博客,低调大师

ES in BI

一直想找一个用于大数据平台实时OLAP(甚至是实时计算)的框架,之前调研的Druid(druid.io)太过复杂,整个Druid由5、6个服务组成,而且加载数据也不太方便,性能一般,亦或是我还不太会用它。后来发现使用ElasticSearch就可以满足海量数据实时OLAP的需求。 ElasticSearch相信大家都很熟悉了,它在搜索领域已经有了举足轻重的地位,而且也支持越来越多的聚合统计功能,还和YARN、Hadoop、Hive、Spark、Pig、Flume等大数据框架兼容的越来越好,比如:可以将ElasticSearch跑在YARN上,还可以在Hive中建立外部表映射到ElasticSearch的Index中,直接在Hive中执行INSERT语句,将数据加载进ElasticSearch。 所谓OLAP,其实就是从事实表中统计任意组合维度的指标,也就是过滤、分组、聚合,其中,聚合除了一般的SUM、COUNT、AVG、MAX、MIN等,还有一个重要的COUNT(DISTINCT),看上去这些操作在SQL中是非常简单的统计,但在海量数据、低延迟的要求下,并不是那么容易做的。 ElasticSearch本来就是做实时搜索的,过滤自然不是问题,现在也支持各种聚合以及Pipeline aggregations(相当于SQL子查询的功能),而且ElasticSearch的安装部署也非常简单,一个节点只有一个服务进程,关于安装配置可参考:http://lxw1234.com/archives/2015/12/582.htm 本文以两个业务场景的例子,看一下ElasticSearch是如何满足我们的需求的。 例子1:网站流量报告 在我们的报表平台有这样一张报表,用于查看每个网站每天的流量指标: 其中,维度有:天、小时、网站,指标有:PV、UV、访问次数、跳出率、平均停留时间、回访率等。另外,还有一张报表是地域报告,维度多了省份和城市,指标一样。目前的做法是将可选的维度组合及对应的指标先在Hive中分析好,再将结果同步至MySQL,供报表展现。 真正意义上的OLAP做法,我是这样做的:在Hive分析好一张最细粒度为visit_id(session_id)的事实表,字段及数据如下: 然后将这张事实表的数据加载到ElasticSearch中的logs2/sitelog1211中。查看数据: curl -XGET 'http://localhost:9200/logs2/sitelog1211/_search?pretty' { "took" : 1015, "timed_out" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 }, "hits" : { "total" : 3356328, "max_score" : 1.0, "hits" : [ { "_index" : "logs2", "_type" : "sitelog1211", "_id" : "AVGkoWowd8ibEMoyOhve", "_score" : 1.0, "_source":{"cookieid" : "8F97E07300BC7655F6945A","siteid" : "633","visit_id" : "feaa25e6-3208-4801-b7ed-6fa45f11ff42","pv" : 2,"is_return_cookie" : 0, "is_bounce_visit" : 0,"visit_stay_times" : 34,"visit_view_page_cnt" : 2, "region" : "浙江","city" : "绍兴"} }, …… 该天事实表中总记录数为3356328。 接着使用下面的查询,完成了上图中网站ID为1127,日期为2015-12-11的流量报告: curl -XGET 'http://localhost:9200/logs2/sitelog1211/_search?search_type=count&q=siteid:1127&pretty' -d ' { "size": 0, "aggs" : { "pv" : {"sum" : { "field" : "pv" } }, "uv" : {"cardinality" : {"field" : "cookieid" ,"precision_threshold": 40000}}, "return_uv" : { "filter" : {"term" : {"is_return_cookie" : 1}}, "aggs" : { "total_return_uv" : {"cardinality" : {"field" : "cookieid" ,"precision_threshold": 40000}} } }, "visits" : {"cardinality" : {"field" : "visit_id" ,"precision_threshold": 40000}}, "total_stay_times" : {"sum" : { "field" : "visit_stay_times" }}, "bounce_visits" : { "filter" : {"term" : {"is_bounce_visit" : 1}}, "aggs" : { "total_bounce_visits" : {"cardinality" : {"field" : "visit_id" ,"precision_threshold": 40000}} } } } }' 基本上1~2秒就可以返回结果: { "took" : 1887, "timed_out" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 }, "hits" : { "total" : 5888, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "uv" : { "value" : 5859 }, "visits" : { "value" : 5889 }, "return_uv" : { "doc_count" : 122, "total_return_uv" : { "value" : 119 } }, "bounce_visits" : { "doc_count" : 5177, "total_bounce_visits" : { "value" : 5177 } }, "pv" : { "value" : 10820.0 }, "total_stay_times" : { "value" : 262810.0 } } } 接着是地域报告中维度为省份的指标统计,查询语句为: curl -XGET 'http://localhost:9200/logs2/sitelog1211/_search?search_type=count&q=siteid:1127&pretty' -d ' { "size": 0, "aggs" : { "area_count" : { "terms" : {"field" : "region","order" : { "pv" : "desc" }}, "aggs" : { "pv" : {"sum" : { "field" : "pv" } }, "uv" : {"cardinality" : {"field" : "cookieid" ,"precision_threshold": 40000}}, "return_uv" : { "filter" : {"term" : {"is_return_cookie" : 1}}, "aggs" : { "total_return_uv" : {"cardinality" : {"field" : "cookieid" ,"precision_threshold": 40000}} } }, "visits" : {"cardinality" : {"field" : "visit_id" ,"precision_threshold": 40000}}, "total_stay_times" : {"sum" : { "field" : "visit_stay_times" }}, "bounce_visits" : { "filter" : {"term" : {"is_bounce_visit" : 1}}, "aggs" : { "total_bounce_visits" : {"cardinality" : {"field" : "visit_id" ,"precision_threshold": 40000}} } } } } } }' 因为要根据省份分组,比之前的查询慢一点,但也是秒级返回: { "took" : 4349, "timed_out" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 }, "hits" : { "total" : 5888, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "area_count" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 2456, "buckets" : [ { "key" : "北京", "doc_count" : 573, "uv" : { "value" : 568 }, "visits" : { "value" : 573 }, "return_uv" : { "doc_count" : 9, "total_return_uv" : { "value" : 8 } }, "bounce_visits" : { "doc_count" : 499, "total_bounce_visits" : { "value" : 499 } }, "pv" : { "value" : 986.0 }, "total_stay_times" : { "value" : 24849.0 } }, { "key" : "山东", "doc_count" : 368, "uv" : { "value" : 366 }, "visits" : { "value" : 368 }, "return_uv" : { "doc_count" : 9, "total_return_uv" : { "value" : 9 } }, "bounce_visits" : { "doc_count" : 288, "total_bounce_visits" : { "value" : 288 } }, "pv" : { "value" : 956.0 }, "total_stay_times" : { "value" : 30266.0 } }, …… 这里需要说明一下,在ElasticSearch中,对于去重计数(COUNT DISTINCT)是基于计数估计(Cardinality),因此如果去重记录数比较大(超过40000),便可能会有误差,误差范围是0~2%。 例子2:用户标签的搜索统计 有一张数据表,存储了每个用户ID对应的标签,同样加载到ElasticSearch中,数据格式如下: curl -XGET 'http://localhost:9200/lxw1234/user_tags/_search?&pretty' { "took" : 220, "timed_out" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 }, "hits" : { "total" : 820165, "max_score" : 1.0, "hits" : [ { "_index" : "lxw1234", "_type" : "user_tags", "_id" : "222222222222222", "_score" : 1.0, "_source":{"sex" : "女性","age" : "27到30岁","income" : "5000到10000","edu" : "本科", "appcategory" : "娱乐类|1.0","interest" : "","onlinetime" : "9:00~12:00|1.0","os" : "IOS|1.0", "hobby" : "游戏|28.57,房产|8.57,服饰鞋帽箱包|28.57,互联网/电子产品|5.71,家居|8.57,餐饮美食|5.71,体育运动|14.29","region" : "河南省"} } ...... 每个用户都有性别、年龄、收入、教育程度、兴趣、地域等标签,其中使用_id来存储用户ID,也是主键。 查询1:SELECT count(1) FROM user_tags WHERE sex = ‘女性’ AND appcategory LIKE ‘%游戏类%'; curl -XGET 'http://localhost:9200/lxw1234/user_tags/_count?pretty' -d ' { "filter" : { "and" : [ {"term" : {"sex" : "女性"}}, {"match_phrase" : {"appcategory" : "游戏类"}} ] } }' 返回结果: { "count" : 106977, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 } } 查询2:先筛选,再分组统计: SELECT edu,COUNT(1) AS cnt FROM user_tags WHERE sex = '女性' AND appcategory LIKE '%游戏类%' GROUP BY edu ORDER BY cnt DESC limit 10; 查询语句: curl -XGET 'http://localhost:9200/lxw1234/user_tags/_search?search_type=count&pretty' -d ' { "filter" : { "and" : [ {"term" : {"sex" : "女性"}}, {"match_phrase" : {"appcategory" : "游戏类"}} ] }, "aggs" : { "edu_count" : { "terms" : { "field" : "edu", "size" : 10 } } } }' 返回结果: { "took" : 479, "timed_out" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 }, "hits" : { "total" : 106977, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "edu_count" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "本科", "doc_count" : 802670 }, { "key" : "硕士研究生", "doc_count" : 16032 }, { "key" : "专科", "doc_count" : 1433 }, { "key" : "博士研究生", "doc_count" : 25 }, { "key" : "初中及以下", "doc_count" : 4 }, { "key" : "中专/高中", "doc_count" : 1 } ] } } } 从目前的调研结果来看,ElasticSearch没有让人失望,部署简单,数据加载方便,聚合功能完备,查询速度快,目前完全可以满足我们的实时搜索、统计和OLAP需求,甚至可以作为NOSQL来使用,接下来再做更深入的测试。 另外,还有一个开源的SQL for ElasticSearch的框架Crate(crate.io),是在ElasticSearch之上封装了SQL接口,使得查询统计更加方便,不过SQL支持的功能有限,使用的ElasticSearch版本较低,后面试用一下再看。

优秀的个人博客,低调大师

SQL for ES

之前介绍过ElasticSearch,它部署简单,搜索聚合功能强大,而且和其他大数据框架整合起来使用,有一点比较不方便,就是查询都需要通过JSON作为请求Body来提交查询,请求响应也是JSON,作为习惯使用SQL的我,迫不及待的试用了一下Crate(crate.io),它是在ElasticSearch之上封装了SQL接口,用户可以通过SQL语句来完成搜索和统计,支持的SQL语法还蛮多的,很想MySQL。 本文记录一下Crate的安装配置(两个节点的Crate集群)和简单使用。 下载和安装Crate 可以从https://cdn.crate.io/downloads/releases/nightly/下载crate的最新版本。 下载后解压到指定目录即可。 配置Crate Crate的配置和ElasticSearch非常类似,以两个节点的Crate集群为例。 cd $CRATE_HOME/conf 编辑crate.yml,修改以下参数: cluster.name: lxw1234_crate node.name: crate_node_17 index.number_of_replicas: 2 path.conf: /home/liuxiaowen/crate-0.54.0/config path.data: /home/liuxiaowen/crate-0.54.0/data path.work: /home/liuxiaowen/crate-0.54.0/tmp path.logs: /home/liuxiaowen/crate-0.54.0/logs path.plugins: /home/liuxiaowen/crate-0.54.0/plugins network.bind_host: 172.16.212.17 network.publish_host: 172.16.212.17 network.host: 172.16.212.17 gateway.recover_after_nodes: 2 discovery.zen.minimum_master_nodes: 2 gateway.expected_nodes: 2 discovery.zen.ping.timeout: 10s discovery.zen.fd.ping_interval: 10s 编辑$CRATE_HOME/bin/crate.in.sh,配置节点使用的内存,根据机器自身内存而定,最大内存一般不要超过物理内存的50%; CRATE_MIN_MEM=8g CRATE_MAX_MEM=16g 配置JAVA_HOME,我这里使用了jdk1.8.0_65 启动Crate 在两个节点上, cd $CRATE_HOME/bin 执行./crate -d 在后台启动Crate,之后可以在配置的path.logs目录下,看到以${ cluster.name }.log命名的日志。 使用Crate命令行 类似于其他数据库,Crate提供了一个命令行来供用户执行SQL查询。 cd $CRATE_HOME/bin 执行./crash进入命令行; 在Crate命令行使用\c 172.16.212.17:4200连接到Crate; 创建表 在Crate命令行使用下面的SQL语句创建表: CREATE TABLE sitelog ( cookieid STRING, siteid STRING, visit_id STRING, pv LONG, is_return_cookie INTEGER, is_bounce_visit INTEGER, visit_stay_times INTEGER, visit_view_page_cnt INTEGER, region STRING, city STRING ); cr> show tables; +------------+ | table_name | +------------+ | sitelog | +------------+ SHOW 1 row in set (0.019 sec) cr> 从外部批量加载数据 crate提供了一个COPY命令,用于从外部文本文件加载数据到表中,但只支持JSON格式的文本,比如: [liuxiaowen@dev sitelog]$ head sitelog_000005_0_9.json {"cookieid" : "DE9C68B401DBE5566A9676","siteid" : "633","visit_id" : "805cdab5-8361-4134-9bbe-7c54771d4dc8","pv" : 1, "is_return_cookie" : 0,"is_bounce_visit" : 1,"visit_stay_times" : 0,"visit_view_page_cnt" : 1,"region" : "江苏","city" : "徐州"} {"cookieid" : "DE9C68B40422A9566A68F2","siteid" : "633","visit_id" : "7f844323-e0c0-48b4-bc1b-69055ac3c308","pv" : 1, "is_return_cookie" : 0,"is_bounce_visit" : 1,"visit_stay_times" : 0,"visit_view_page_cnt" : 1,"region" : "江苏","city" : "徐州"} {"cookieid" : "DE9C68B4066B7F566A6F36","siteid" : "633","visit_id" : "045c3a13-41bf-45c4-93ce-7725a00ada5f","pv" : 1, "is_return_cookie" : 0,"is_bounce_visit" : 1,"visit_stay_times" : 0,"visit_view_page_cnt" : 1,"region" : "江苏","city" : "徐州"} JSON对象中的k需要和表的字段名称相同。 在Crate命令行使用COPY命令加载数据: 加载的速度还是非常快的。 SQL查询 可以从Crate官网上查看支持的SQL语法:https://crate.io/docs/reference/sql/dql.html 值得关注的是,Crate在做COUNT DISTINCT查询的时候,查出来的是真实去重后的数,没有误差,但查询响应时间要慢一些,有待研究。 Crate的监控界面 Crate提供了一个比较炫的监控界面,非常有用,Crate集群启动后,在浏览器输入:http://172.16.212.102:4200/admin/ 进入监控界面: OverView页面:集群整体健康及负载状况。 Tables页面:Crate中所有Table及Schema的情况。 Cluster页面:Crate集群的节点列表及每个节点的健康状况。 Crate的不足 目前只是简单安装试用了一下,发现了几点不足: 不支持子查询; 不支持诸如CASE WHEN、IF ELSE的逻辑判断语法,特别是在聚合函数中; 内置的ElasticSearch版本太低; 没有和其他大数据组件的整合。 但它的查询性能还是很不错的,关键是SQL方便啊。

优秀的个人博客,低调大师

ES TransportClient demo

import java.net.InetAddress; import java.net.UnknownHostException; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import java.lang.*; public class ESClientTest { public static void main(String[] args) throws UnknownHostException { Settings settings = Settings.builder().put("client.transport.sniff", true).build(); TransportClient transportClient = new PreBuiltTransportClient(settings) .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("10.178.209.160"), 9300)); String json = "{" + "\"user\":\"kimchy\"," + "\"postDate\":\"2013-01-30\"," + "\"message\":\"trying out Elasticsearch\"" + "}"; /* * IndexResponse response = transportClient.prepareIndex("twitter", * "tweet").setSource(json).execute().actionGet(); * System.out.println(response.toString()); */ BulkRequestBuilder bulkRequest = transportClient.prepareBulk(); bulkRequest.add(transportClient.prepareIndex("twitter", "tweet", "1").setSource(json)); long t1 = System.currentTimeMillis(); BulkResponse response1 = bulkRequest.get(); System.out.println(System.currentTimeMillis() - t1); if (response1.hasFailures()) { System.err.println(response1.buildFailureMessage()); } else { System.out.println( "Bulk indexing succeeded." + response1.toString() + " time:" + response1.getTookInMillis()); } transportClient.close(); } } 本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/7994161.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册