ES的入门学习

一、开场白

1、哪些人需要学习ES

  • 开发

  • 测试

  • 运维

  • 利用数据来分析和查询的人

作为一个非关系型数据库,有着和mysql关系型数据库一样重要的地位。

2、学习ES需要具备什么基础

  • 会写SQL语句

  • json格式

  • http请求

3、入门学习ES的内容

1)动手操作安装起来,最新的ES版本已经是7.4.2了。

官网https://www.elastic.co/cn/downloads/elasticsearch下载适合你OS版本的程序,解压缩并启动即可。

image.png

2)基于head插件或kibana的操作

3)简单理解为什么ES如此受欢迎,能够支持亿级数据。

4)ES是怎么支持关键词查询的

二、ES的几个知识点

1、和mysql的对比

数据库 字段 DDL
mysql Database Table Row Column create table
ES Index 索引 Type 类型 Document 文档 Field 字段 Mapping
客户端工具 复制方式
mysql navicat, SQLyog, MySQL Workbench 主从
ES elasticsearch-head, Kibana, Elasticsearch-sql, Elasticsearch-HQ 对等

es在5.x以后,没有了string类型,被拆分为关键词搜索keyword和全文搜索text。

keyword text
自动分词
支持聚合

ES支持多种数据类型,除了上面说的字符串类型,还有日期,布尔,二进制,还有geo,IP,Multi-fields等实用的类型。

2、集群、节点、分片、副本

1)集群与节点

集群一般要有3个节点,分开主分片和副本。

2)节点与分片

节点按角色可分为数据节点、主节点、协同节点。

分片数 = 节点数的1.5 ~ 3倍

3)分片与副本

副本是可以随时调整的,但分片指定后不可变。一般,一个分片有1~2个副本即可保证高可用。

请问下面的这个集群,有多少节点,多少分片,多少主分片,多少副本???

image

注意:集群下的分片数 = 索引的主分片数 * (1 + 副本数)

200GB的数据建议分片数为7~8个。(ES JVM heap 最大可以设置32G 。 30G heap 大概能处理的数据量 10 T。)

集群的状态 说明
yellow 所有主分片可用,但不是所有副本分片都可用。或者,硬盘空间超过85%
green 所有的主分片和副本分片都可用
red 部分主分片不可用

在同一个节点上既保存原始数据又保存副本是没有意义的,因为一旦失去了那个节点,我们也将丢失该节点上的所有副本数据。开发环境单节点的情况下,由于es默认是有1个副本,主分片和副本不能在同一个节点上,所以副本就是未分配unassigned。新建索引像下面这样建立:

{
 "settings":{
 "number_of_shards":1, 
 "number_of_replicas":0
 }
}

3、倒排索引

注意:不需要索引的字段,一定要明确定义出来,因为默认是自动创建索引的。

@Field(type = FieldType.text , index = FieldIndex.not_analyzed)
private String message;

比如有一个表User

ID Name Age Sex
1 Tom 18 Male
2 Kate 18 Female
3 Jack 19 Male

ES分别为每个field都建立一个倒排索引

Term Posting List ( 存储所有符合term的文档id)
18 [1,2]
19 [3]

现在的问题是如何快速查找到某个Term?

image

1)提高查询效率,mysql的B+树通过减少磁盘寻道次数,ES直接通过内存查找Term,不读磁盘。

但是如果Term太多,Term Dictionary也会很大,导致内存放不下。

2)于是就有了Term Index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解term index是一颗树。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。

image

注意:这棵树不会包含所有的term,它包含的是term的一些前缀。

3)把term index缓存到内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘随机读的次数。

(这里遗留一个问题,如果Term Index树还是很大怎么办?)

4、分词器

注意:对于String类型的字段,不需要analysis的也需要明确定义出来,因为默认是会analysis的。

@Field(type = FieldType.keyword)
private String message;

分词是将文本转换成一系列单词(Term or Token)的过程,也可以叫文本分析,在ES里面称为Analysis

@Field(type = FieldType.keyword ,analyzer = "ik_smart", searchAnalyzer = "ik_smart")
private String name;

分词器,推荐支持中文的ik-analyzer,详情参考Elasticsearch 默认分词器和中分分词器之间的比较及使用方法

5、压缩技巧

1)term index:用确定无环状态转换器(Deterministic acyclic finite state transducer, FST)压缩,以字节的方式存储所有的term。

(FST压缩率一般在3倍~20倍之间,相对于TreeMap/HashMap的膨胀3倍,内存节省就有9倍到60倍!)

我们对“october”,“november”, ”december”这三个词构建确定无环有限状态接收机(Deterministric acyclic finite state acceptor, FSA),如下:

image

(TRIE树只共享前缀,而FSA不仅共享前缀还共享后缀。)

我们对“mar”,“jul”,“jun”这三个词构建FST,如下:

image

(FST保证了不同的转移有唯一的值:mar的值为3,jul的值为7, jun的值为6。)

详细请参考 关于Lucene的词典FST深入剖析

2)posting list:增量编码压缩,将大数变小数,按字节存储。

Frame Of Reference压缩算法:

image

3)内存缓存数据:Roaring bitmaps,高效压缩解压和逻辑运算。

Bitmap是一种数据结构,假设有某个posting list:[1,3,4,7,10] 对应的bitmap就是:[1,0,1,1,0,0,1,0,0,1]

Bitmap的缺点是存储空间随着文档个数线性增长,

Roaring bitmaps需要打破这个魔咒就一定要用到某些指数特性:将posting list按照65535(=2^16-1,一个short的存储单位)为界限分块,比如第一块所包含的文档id范围在065535之间,第二块的id范围是65536131071,以此类推。再用<商,余数>的组合表示每一组id,这样每组里的id范围都在0~65535内了。

image

If a block has more than 4096 values, encode as a bit set, and otherwise as a simple array using 2 bytes per value

6、记得给索引取别名

巧妙利用这点,在你想修改某个字段的类型,或删除某个字段的时候,而不想修改代码的时候,作用就很明显了。当你的存储数据是基于时间序列规则的时候,你只要使用别名查询,ES会自动聚合。

image.png

好处是代码使用别名,只要别名一致,无论ES这么折腾,不会让你去修改代码。

三、文档的CRUD

ES提供了一套对外的restful api接口,让你操作变得规范和易懂。

详见官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.1/docs.html

image.png
操作类型 普通请求 批量操作
查询 _search + GET _mget + GET
新增 _create + PUT _reindex + POST
删除 DELETE _delete_by_query + POST
修改 _update + POST _update_by_query + POST

1、创建索引

1)head插件:

开发环境地址: http://192.168.5.57:9100/

image.png

image.png

如果是单节点,非集群环境下,可以像下面这样设置作为测试:


image.png

image.png

新建成功后,可以在概览界面看到刚创建的索引user:


image.png

选择”动作“--》”删除“,在弹出框输入字符”删除"确认,便可以删除user索引。


image.png

看到如下弹出框,说明删除成功!!


image.png

2)postman

注意:请求方式是PUT,请求URL是http://192.168.5.57:9200/user , user是要创建的索引名。

image.png

删除索引,选择请求方式为DELETE


image.png

3)curl 等工具

curl -X PUT 'http://192.168.5.57:9200/user'
​
curl -X DELETE 'http://192.168.5.57:9200/user'

4)head自带的http请求,理解这一点很重要,后面数据的查询和增删改,通过这点都能实现。

创建索引


image.png

删除索引


image.png

2、查询数据

1)简单查询

它只能做查询搜索,不能创建、修改和删除数据,如果想要执行这些操作,那就只能用下一个功能块“复合查询”了。

索引reader有98个document,也就是我们说的98条记录,id字段是主键。


image.png

返回格式,你也可以选择json和csv格式:


image.png

下面是csv格式,支持导出。(亮点哦,建议我们所有的数据分析,打印的数据格式都是csv)


image.png

这里虽然说是基本查询,其实是支持多条件的查询了,类似navicat的查询。所以有必要再讲下使用。

  • must 返回的文档必须满足must子句的条件,类似于 == and

  • must not返回的文档必须不满足must not 子句的条件 类似于!= not

  • should 返回的文档只要满足should中的一个条件即可 类似于 || or

参数含义:

查询参数 含义
term 相当
wildcard 通配符查询 例:* 商品 *
prefix 前缀
fuzzy 区间,分词模糊查询 结合max_expansions 和min_similarity,数值则表示在此数值的增加,减小数量在多少范围之内的数据;字符则为在此自负基础上增加/减少多少字符范围内的数据
range 区间查询,如果type是时间类型,可用内置now表示当前,-1d/h/m/s来进行时间操作
query_string 可以对int, long, string查询,对int,long只能本身查询,对string进行分词和本身查询
text 片段
missing 返回没有字段或值为null的文档

另外:gt/lt/gte/lte就不解释了。

postman查询:地址http://192.168.5.57:9200/user/_search ,请求方式是GET,多条件查询建议使用上面的head。

image.png

如果你是指定id查询,末尾就不需要加_search了。否则会报错

No handler found for uri [/user/collect/3/_search] and method [GET]


image.png

2)复杂查询

相当于postman了,支持发送RESTful API到elasticsearch服务执行。

注意:勾选”易读“,对json文本进行格式化。复杂查询就不单是查询了,还支持增删改。

image.png

3、新增数据

1)指定index的type和id:


image.png

可以看到新增了一条记录。。。


image.png

image.png

上面是id指定,也可以让ES自动生成,但是不建议使用自增的方式插入数据:


image.png

这里大家可能会有疑问,user我知道是索引,那collect是啥子呢,是我们定义的type了,也就是表名。es是非关系型数据库,好处就是灵活。你可以自定义_type。


image.png
方便大家测试,我将user的属性json文本拷贝出来,仅供参考:
​
{
 "name": "测试12",
 "age": "18",
 "gender": "male",
 "ctime": "",
 "utime": ""
}

ES索引的field是很灵活的,不用管总共有哪些field,只写你所需要的就好。

{
 "name": "测试14",
 "gender": "male"
}

当然也可以使用postman等工具哈,归功于ES对外很好的restful api接口。


image.png

4、修改数据

根据主键的唯一性,进行覆写操作。

请求地址为http://192.168.5.57:9200/reader/collect/47/ , 格式是http://192.168.5.57:9200/<_index>/<_type>/<_id> , 操作类型是_update(指明是修改操作),http请求方式是POST。

postman工具,请求地址是http://192.168.5.57:9200/user/collect/4/_update , 请求方式还是post

{ 
 "doc":{
 "name": "测试4"
 }
}

支持条件修改:

请求地址是:http://192.168.5.57:9200/user/_update_by_query/ ,请求方式是POST。

{
 "query": {
 "match": {
 "name": "zhangsan"
 }
 }
}

5、删除数据

请求地址为http://192.168.5.57:9200/user/collect/AW6g18C-QJexQIWLsAxW/ 格式是http://192.168.5.57:9200/<_index>/<_type>/<_id> ,http请求方式是DELETE。

支持条件删除:

请求地址是:http://192.168.5.57:9200/user/_delete_by_query/, 请求方式是POST

query如何来,建议从head的简单查询视图里拷贝。

{
 "query": {
 "match": {
 "name": "zhangsan"
 }
 }
}

四、Mapping

个人理解这个类似于mysql的DDL语句,上面讲述的crud是属于DML语句。为什么说类似,而不完全是呢?mysql修改一个字段的类型轻轻松,ES会让你的工作绕一大圈子!!

1、查看mapping

在创建索引的时候,一起定义映射:

请求地址:http://192.168.5.57:9200/user ,请求方式PUT。

{
 "settings":{
 "index":{
 "number_of_shards":1,
 "number_of_replicas":0
 }
 },
 "mappings":{
 "collect":{
 "properties":{
 "name":{
 "type":"text"
 },
 "age":{
 "type":"long"
 },
 "gender":{
 "type":"keyword"
 },
 "message":{
 "type":"text",
 "index":"not_analyzed"
 },
 "ctime":{
 "type":"long"
 },
 "utime":{
 "type":"long"
 }
 }
 }
 }
}

查看mapping

请求地址:http://192.168.5.57:9200/user/_mapping/, 请求方式GET

image.png

image.png

2、新增mapping:

请求地址是http://192.168.5.57:9200/user/collect/_mapping ,主要要指定index和type。

image.png

3、修改mapping

准确的说,是新增字段,而不是修改原有的字段类型。如果你需要修改,怎么办?要么删除索引重新导入,要么reindex。有时候请想下新增字段是不是能够解决你的需求~~请参考https://www.cnblogs.com/royfans/p/11436395.html

postman操作:


image.png

head操作:


image.png

你可能感兴趣的:(ES的入门学习)