上一篇文章里面讲到了elk的安装,这次来说一下如何进行查询。
进入kibana之后,是没有任何东西可以查的。首先要设置index。
在kibana的management里面,进入index object
,在里面创建index。
创建完成之后,就可以在Discover
里面进行查询了。Discover
里面,左侧列出来的就是一些字段以及字段的类型。
我还是喜欢在Dev tools
里面,使用json形式进行查询,如下图所示:
看上面这张图,hits
字段里面的total
表示命中了4229条记录,但实际返回的只有10
个具体的记录,这是因为ES默认返回10条记录。
如果想要更多的记录,或者是某个分片的记录,可以用scroll查询或者是分片查询。
scroll查询 vs 分片查询
scroll查询
scroll查询分成两个部分
- 初始化scroll查询。
- 之后的滚动查询
-
先来看如何初始化scroll查询,看下面这张示例图:
1.1 url格式为
yourindexname/_search?scroll=xxm
,scroll的取值表示查询游标的过期时间。1.2 查询结果里面,会有
_scroll_id
字段。之后就可以用这个id来进行滚动查询 -
再来看如何进行滚动查询。看下面这种示意图:
2.1 url个格式为
_search/scroll
,注意前面不要再加上yourindexname
2.2 查询参数里面只需要传入
scroll_id
和scroll
。scorll_id
就是刚刚初始化的时候拿到的,scroll
表示游标的过期时间2.3 返回结果里面,也是默认10条记录。如果要取得所有的记录,那么就要不断的滚动查询,知道最后。如果游标过期了,那么返回的结果会报
"status": 404
之类的错
分片查询
上面说的是滚动查询也叫游标查询。再来说说分片查询。
MySql里面有limit关键字,可以进行分片查询,比如说select * from your_table_name limit 10, 20;
表示从表里面的第10条记录开始(包括第十条),获取20条结果。
在ES里面,用from和size也可以进行分片查询,如下所示
GET parsed-nginx-access-log/_search
{
"query": { "match_all": {}},
"from": 10,
"size": 20
}
两者的区别
- scroll不太适合做实时查询,比较适合做后台批量任务。
- scroll分为初始化和遍历两部分
- 分片查询如果是深度分片,会有一系列性能问题。
关于深度分片,这就要说到查询的两个阶段:
查询分成两个阶段,一个是query阶段,一个是fetch阶段。query阶段是确定需要取那些doc,fetch是把这些doc取出来。
例如使用下面这个示例,
GET parsed-nginx-access-log/_search
{
"query": { "match_all": {}},
"from": 10,
"size": 20
}
query阶段
-
Client 发送一次搜索请求
-
node1 接收到请求,node1 创建一个大小为 from + size 的优先级队列用来存结果,我们管 node1 叫 coordinating node。
-
coordinating node将请求广播到涉及到的 shards
-
每个 shard 在内部执行搜索请求,每个shared用大小为from + size的队列存储doc_id。每个shared在query阶段只需要返回唯一标记 doc 的 _id 以及用于排序的 _score 即可,这样也可以保证返回的数据量足够小。每个 shard 把暂存在自身优先级队列里的数据返回给 coordinating node
-
coordinating node 拿到各个 shards 返回的结果后对结果进行一次合并,排序后产生一个全局的优先级队列,存到自身的优先级队列里。
在上面的例子中,coordinating node 拿到 (from + size) * 6 条数据,然后合并并排序后选择前面的 from + size 条数据存到优先级队列,以便 fetch 阶段使用。另外,各个分片返回给 coordinating node 的数据用于选出前 from + size 条数据,所以coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。
fetch阶段
query阶段知道了要取哪些doc,得到的是这些doc的id。fetch阶段是真正要取这些doc
上图展示了 fetch 过程:
-
coordinating node 发送 GET 请求到相关shards。
-
shard 根据 doc 的 _id 取到数据详情,然后返回给 coordinating node。
-
coordinating node 返回数据给 Client。
注意:
-
coordinating node 的优先级队列里有 from + size 个 _doc _id,但是,在 fetch 阶段,并不需要取回所有数据,在上面的例子中,第0条到第9条数据是不需要取的,只需要取优先级队列里的第10到条到第20条数据即可。
-
需要取的数据可能在不同分片,也可能在同一分片,coordinating node 使用 multi-get 来避免多次去同一分片取数据,从而提高性能。
-
深度分页可能会引起一些问题,比如说CPU,内存,IO,网络带宽等。