面试题答案
一键面试1. 对 query_string 的优化
- 精确匹配优先:如果部分字段适合精确匹配,优先使用精确匹配语法。例如在一个电商商品查询场景中,若用户输入商品编号查询,使用
term
查询比query_string
更高效。比如使用 Elasticsearch,假设商品索引为products
,商品编号字段为product_id
,查询商品编号为12345
的商品:
{
"query": {
"term": {
"product_id": "12345"
}
}
}
这样可以避免query_string
可能的分词开销,提升查询效率。
- 合理分词:对于需要全文搜索的
query_string
,配置合适的分词器。例如在新闻文章搜索场景中,对于中文文章,使用ik_max_word
分词器比默认分词器更适合中文文本。假设新闻索引为news
,文章内容字段为content
,查询包含“人工智能”的新闻:
{
"query": {
"query_string": {
"fields": ["content"],
"query": "人工智能",
"analyzer": "ik_max_word"
}
}
}
- 减少通配符使用:通配符查询(如
*
和?
)开销较大,尽量避免在开头使用。如果必须使用,可以先通过其他更精确的条件过滤,再使用通配符。例如在搜索文件名场景中,先通过文件类型等过滤,再用通配符匹配文件名部分。假设文件索引为files
,文件类型字段为file_type
,文件名字段为file_name
,先查询类型为pdf
且文件名包含report
的文件:
{
"query": {
"bool": {
"must": [
{
"term": {
"file_type": "pdf"
}
},
{
"wildcard": {
"file_name": "*report*"
}
}
]
}
}
}
2. 对 filter 的优化
- 使用缓存:对于不经常变化的过滤条件,可以利用缓存。例如在一个地区统计系统中,查询某个固定地区的数据,假设地区为
北京
,如果查询频率高且数据更新不频繁,可以在应用层缓存该查询结果。在代码中可以使用 Redis 缓存,Python 示例如下:
import redis
import requests
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)
region = '北京'
cache_key = f'region_{region}_data'
data = redis_client.get(cache_key)
if not data:
response = requests.get(f'http://your_api_url?region={region}')
data = response.json()
redis_client.set(cache_key, data)
print(data)
- 条件合并:如果有多个过滤条件,可以尝试合并条件。例如在一个用户管理系统中,要查询年龄在 18 到 30 岁之间且性别为男的用户,在 SQL 中可以这样写:
SELECT * FROM users WHERE age BETWEEN 18 AND 30 AND gender = '男';
而不是先查询年龄范围,再在结果中过滤性别,减少中间结果集的生成。
- 利用索引:确保过滤字段上有合适的索引。例如在电商订单系统中,经常按订单状态过滤订单,在
order_status
字段上创建索引。在 MySQL 中:
CREATE INDEX idx_order_status ON orders(order_status);
3. 对 sort 的优化
- 选择合适排序字段:尽量选择有索引的字段排序。例如在博客文章系统中,按发布时间排序,假设发布时间字段为
publish_time
,在该字段创建索引:
CREATE INDEX idx_publish_time ON blog_posts(publish_time);
然后在查询时:
SELECT * FROM blog_posts ORDER BY publish_time DESC;
- 减少排序字段数量:如果不是必要,尽量只按一个字段排序。多个字段排序会增加系统开销。例如在产品列表中,优先按销量排序即可满足需求,就不要同时按销量和价格排序。
- 分页时优化:在分页场景下,使用
scroll
或者search_after
方式替代简单的from
和size
分页。例如在 Elasticsearch 中,使用search_after
进行分页查询:
{
"query": {
"match_all": {}
},
"sort": [
{
"publish_time": "desc"
}
],
"size": 10,
"search_after": [1609459200] // 上一页最后一条记录的 publish_time 值
}
这样避免了深度分页时from
值过大导致的性能问题。