优化从索引片段,内存设置,副本,分片,日志等方面入手。
1:索引片段
Es运行时会生成很多索引片段,执行查询时会打开这些索引片断。系统会限制打开索引片断的个数一旦超过这个个数限制就无法打开索引片断。我们可以通过命令来查看更改索引片断的限制数量。
索引片断位置
/usr/local/elasticsearch-1.4.4/data/elasticsearch/nodes/0/indices/shb01/0/index

ulimit –a 查看索引片断数量,默认是1024


ulimit -n 32000 更改索引片断数量



如果索引片断太多会影响效率我们可以在es集群空闲时对索引片断进行合并。合并可以通过curl命令和Java来实现。
Curl
curl -XPOST http://192.168.79.131:9200/shb01/_optimize?max_num_segments=1

java

[java] view plain copy
  1. /** 
  2.      * 合并索引片段  
  3.      */  
  4.     @Test  
  5.     public void testOptimize()  
  6.     {  
  7.         transportClient.admin().indices().prepareOptimize("shb01""shb02")  
  8.                 .setMaxNumSegments(1).get();  
  9.     }  
curl命令可以在linux中建立一个定时任务每天执行一次,同样java代码也可以建立一个定时器来执行。

2:内存设置
之前介绍过es集群有两种启动方式
第一种是bin目录下bin/ elasticsearch
打开/usr/local/elasticsearch-1.4.4/bin/elasticsearch.in.sh文件修改文件中的两个参数,将ES_MIN_MEM=256m和ES_MAX_MEM=1g的值改成一样一般设置为可用内存的60%,这样可以避免频繁的内存交换。
另一种是searchwrapper插件方式启动bin/service/ elasticsearch start
打开/usr/local/elasticsearch-1.4.4/bin/service/修改set.default.ES_HEAP_SIZE=1024

另外在es的配置文件中修改bootstrap.mlockall: true,这样禁止内存交换。

3:分片设置
Es将数据存储在多个分片中那么分片的数量就影响到了查询效率。
分片数少了导致分片过大打开一个太大的分片太慢,分片数量过多查询时会打开过多的分片而且还有多台服务器之间的通信问题。所以过多过少都不行,一般情况下分片数量维持在5~20个之间单个分片最大不要超过20G。我们可以根据实际的业务来评估分片数量。
比如我有5个分片,预计3个月会产生100G的数据,那么我们可以每3个月当5个分片达到20G时就重新建立一个索引库。


4:副本设置
副本多了可以增强es集群的安全性提高搜索能力但是也会相应的增加服务器同步数据的压力,一般可以设置2~3个副本即可。
另外当初次建立索引库时需要大量倒入数据时我们可以临时将副本改为0不让其同步数据以减轻服务器压力,倒入完成后通过mappings来更改副本数,这种方式只针对当前索引库后期添加的索引库仍会读取elasticsearch.yml中的副本个数,es重启后仍然会保持之前mappings修改的副本数。

5:删除文档
在es中删除一个文档后不会立即从硬盘中删除只会标记这个文档被删除,lucene会产生一个.del文件,而在检索过程中这个文件还会参与检索只不过在最后会被过滤掉,这样其实也会影响效率,我们可以定期删除这些文件,同合并索引片断一样可以通过curl和java两种方式来执行。
Curl
curl -XPOST http://192.168.79.131:9200/_optimize?only_expunge_deletes=true
Java

[java] view plain copy
  1. /** 
  2.  * 删除.del文件  
  3.  */  
  4. @Test  
  5. public void testOptimizeDel()  
  6. {  
  7.     transportClient.admin().indices().prepareOptimize("shb01""shb02")  
  8.             .setOnlyExpungeDeletes(true).get();  
  9. }  


6:日志输出
可以调整es的日志级别,es的默认级别是trace,超过500ms就属于慢查询就需要打印日志,一般改为info或error级别。
日志文件/usr/local/elasticsearch-1.4.4/config/logging.yml
ndex.search.slowlog: TRACE, index_search_slow_log_file 将TRACE改为INFO
或者更改elasticsearch.yml文件中对于慢查询的设置
index.search.slowlog.threshold.query.trace: 500ms 

7:单态获取es对象
在java代码中使用单实例的方式来获取org.elasticsearch.client.transport.TransportClient对象。

8:es极速查询
Es将数据存储在不同的分片中,根据文档id通过内部算法得出要将文档存储在哪个分片上,所以在查询时只有指定在对应的分片上进行查询就可以实现基于es的极速查询,但是前提是你需要知道数据在那个分片上。
还可以通过路由参数来设置数据存储在同一个分片中,setRouting(“”)

[java] view plain copy
  1. /** 
  2.      * 路由参数  
  3.      */  
  4.     @Test  
  5.     public void testRoutingInsert()  
  6.     {  
  7.         String source = "{\"name\":\"中山大学l\",\"num\":1800}";  
  8.         IndexResponse indexResponse = transportClient.prepareIndex(index, "stu")  
  9.                 .setRouting("student")  
  10.                 .setSource(source).get();  
  11.         System.out.println(indexResponse.getVersion());  
  12.     }  
  13.       
  14.     /** 
  15.      * 路由参数  
  16.      */  
  17.     @Test  
  18.     public void testRoutingSearch()  
  19.     {  
  20.         SearchResponse searchResponse = transportClient.prepareSearch(index)  
  21.                 .setTypes("stu")  
  22.                 .setQuery(QueryBuilders.matchAllQuery())  
  23.                 //.setPreference("_shards:0,1,2")  
  24.                 .setRouting("student""teacher")  
  25.                 .get();  
  26.           
  27.         SearchHits hits = searchResponse.getHits();  
  28.         SearchHit[] hits2 = hits.getHits();  
  29.         for(SearchHit h : hits2)  
  30.         {  
  31.             System.out.println(h.getSourceAsString());  
  32.         }  
  33.     }  

9:去掉mapping中_all域