一、使用场景介绍

elasticsearch除了普通的全文检索之外,在很多的业务场景中都有使用,各个业务模块根据自己业务特色设置查询条件,通过elasticsearch执行并返回所有命中的记录的id;如果命中的记录数达到数万级别的话,查询性能会有明显的下降,尤其是命中超大型的document的时候;

获取记录的id目前可以使用的有三种方式;

通过_source:["id"]

设置_source:false,通过es返回的元数据_id分离出device的id;

使用store=true来单独的存储device id,查询的时候使用stored_fields= ['id'];

二、store映射参数

默认情况下,字段值会被索引以使其可搜索,但不会存储它们。这意味着可以查询该字段,但不能检索原始字段值。

通常这并不重要。该字段值已经是_source字段的一部分,该字段是默认存储的。如果您只想检索单个字段或几个字段的值,而不是整个_source,那么可以通过_source过滤来实现。

在某些情况下,存储字段是有意义的。例如,如果你有一个文档,一个标题,一个日期,和一个非常大的内容字段,你可能想只检索标题和日期,而不必从一个大的_source字段提取这些字段:

设置对应字段的store参数为true,并创建mapping;

PUT my_store_test
{
"mappings": {
"_doc": {
"properties": {
"title": {
"type": "text",
"store": true
},
"date": {
"type": "date",
"store": true
},
"content": {
"type": "text"
}
}
}
}
} {
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_store_test"
}

put一个document进行索引

PUT my_store_test/_doc/1
{
"title": "Some short title",
"date": "2015-01-01",
"content": "A very long content field..."
} {
"_index" : "my_store_test",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}

通过在查询语句中设置stored_fields来筛选要返回的字段,elasticsearch返回的fields字段包含对应的字段值;

GET my_store_test/_search
{
"stored_fields": [ "title", "date" ]
} {
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_store_test",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"fields" : {
"date" : [
"2015-01-01T00:00:00.000Z"
],
"title" : [
"Some short title"
]
}
}
]
}
}

三、测试情况

我们测试使用my_store_index,里边包含50W的document,还有一些特别大的document;

我们fetch_ids_query进行测试

默认情况下通过elasticsearch查询返回的_source字段获取记录的id字段;

通过take_from__id控制从elasticsearch查询返回的元数据_id解析出记录id;

通过task_stored_fields控制从elasticsearch查询返回的fields获取记录的id;

from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
import time def fetch_ids_query(client, take_from__id = False, task_stored_fields = False):
start = time.time()
s = Search(using=client, index="my_store_index")
s = s.params(http_auth=["test", "test"], request_timeout=50);
q = Q('bool',
must_not=[Q('match_phrase_prefix', name='us')]
)
s = s.query(q) s = s.source(False) if take_from__id else s.source(['id'])
if task_stored_fields:
s = s.extra(stored_fields= ['id'])
s = s.source(False) s = s[0:40000]
response = s.execute() print(f'hit total {response.hits.total}')
print(f'fetch total {len(response.hits.hits)}') ids = []
if take_from__id:
for hit in response.hits.hits:
id = hit['_id'][37:]
ids.append(id)
elif task_stored_fields:
for hit in response.hits.hits:
id = hit.fields['id'][0]
ids.append(id)
else:
for hit in response.hits.hits:
id = hit._source['id']
ids.append(id) end = time.time()
print(f"all execute time {end - start}s") client = Elasticsearch(hosts=['http://127.0.0.1:9200'], http_auth=["test", "test"]) print('fetch id from source')
fetch_ids_query(client);
print()
print('fetch id from _id and set source = false')
fetch_ids_query(client, True);
print()
print('fetch id from stored id and set source = false')
fetch_ids_query(client, False, True);

四、测试结果

经测试在命中484970,fetch 40000条记录的前提下,后两种方式的执行时间更短,但是通过元数据解析_id会更加友好,不仅节省存储空间,而且查询的时候避免了内存和CPU的震荡;

fetch id from source
hit total 484970
fetch total 40000
all execute time 28.691869497299194s fetch id from _id and set source = false
hit total 484970
fetch total 40000
all execute time 11.315539121627808s fetch id from stored id and set source = false
hit total 484970
fetch total 40000
all execute time 13.930094957351685s

elasticsearch查询之三种fetch id方式性能测试的更多相关文章

  1. 05.Python网络爬虫之三种数据解析方式

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  2. Python爬虫之三种数据解析方式

    一.引入 二.回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需 ...

  3. 05,Python网络爬虫之三种数据解析方式

    回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...

  4. 《Python网络爬虫之三种数据解析方式》

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  5. Katalon Studio入门学习之三种获取元素方式

    Katalon Studio中元素属性定位有三种方式,分别是XPath.Attributes(元素).CSS(样式),KS的界面展示如右图 打开网站,按F12或进入浏览器设置->更多工具-> ...

  6. Python网络爬虫之三种数据解析方式 (xpath, 正则, bs4)

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  7. Python网络爬虫之三种数据解析方式

    1. 正则解析 正则例题 import re # string1 = """<div>静夜思 # 窗前明月光 # 疑是地上霜 # 举头望明月 # 低头思故乡 ...

  8. 【原】iOS学习之三种拨打电话方式的比较

    拨打电话小编从网上找到三种,在这里做一些总结和比较 1.基本使用 NSString *str = [[NSMutableString alloc] initWithFormat:@"tel: ...

  9. 一种更高查询性能的列存储方式MaxMinT 第一部分

    简介本文描述了一种列存储方式和对应的查询方法,这种存储方式具有更好的查询性能和更小的存储空间. And查询 本文先用直观的图形方式展示and查询时的方式,这也是算法要解决的问题核心.通常在OLAP数据 ...

随机推荐

  1. Go语言发邮件

    发送邮件是实际业务中经常会用到的一个功能,而在Go语言中实现发送邮件的库也有很多,这篇文章将介绍go语言中如何发邮件. 1. 登录QQ邮箱,选择账户,开启POP3/SMTP服务和IMAP/SMTP服务 ...

  2. WebLogic任意文件上传漏洞(CVE-2019-2725)

    一,漏洞介绍 1.1漏洞简介 Oracle weblogic反序列化远程命令执行漏洞,是根据weblogic的xmldecoder反序列化漏洞,只是通过构造巧妙的利用链可以对Oracle官方历年来针对 ...

  3. mybatis(1.2)

    为什么执行sql语句后 数据库表中不会更新 需要我们手动配置  两种方法 如下: 1:调用SqlSession接口的commit方法 2:获取Session的时候  SqlSessionFactory ...

  4. HDUA/B

    同样求逆元的题目,费马的条件,首先要保证p为质数,然后保证a与p互素. 数据范围问题,要保证在数据范围内,所以要b先模上mod #include<bits/stdc++.h> using ...

  5. 【Java】成员变量赋值执行顺序

    程序中成员变量赋值的执行顺序

  6. actf2020upload

    actf2020upload .php后缀过滤 1.上传文件,要求后缀为.png/.gif/.jpg 2.抓包,后缀改成.phtml后放行,上传成功,访问地址,根目录下找到flag

  7. winform创建桌面快捷方式

    //引用IWshRuntimeLibrary COM组件-Windows Script Host Object Model /// <summary> /// 创建快捷方式的类 /// & ...

  8. VS IDE之xml过大报错

    语料处理时遇到这个错误 在命令行中输入 $vsWherePath = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\ ...

  9. ServletContext接口

    Servlet 容器启动时,会为每个 Web 应用(webapps 下的每个目录都是一个 Web 应用)创建一个唯一的 ServletContext 对象,该对象一般被称为"Servlet ...

  10. 安卓开发之intent

    两个活动之间的跳转要通过intent来进行,intent跳转分为隐式的和显示的. 首先xml中定义Button,通过按下按钮实现回调,在回调函数中进行相应intent设置. <Button an ...