optimize single shard search (or search result) by not doing another round of sorting

This commit is contained in:
kimchy 2011-02-02 13:52:34 +02:00
parent 8c196d8b84
commit 0bce34cb5a
3 changed files with 94 additions and 2 deletions

View File

@ -27,7 +27,9 @@ import org.elasticsearch.common.collect.Iterables;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.collect.Maps;
import org.elasticsearch.common.collect.Ordering;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.trove.ExtTIntArrayList;
import org.elasticsearch.common.trove.impl.Constants;
import org.elasticsearch.common.trove.map.hash.TObjectIntHashMap;
@ -53,7 +55,7 @@ import java.util.Map;
/**
* @author kimchy (shay.banon)
*/
public class SearchPhaseController {
public class SearchPhaseController extends AbstractComponent {
public static Ordering<QuerySearchResultProvider> QUERY_RESULT_ORDERING = new Ordering<QuerySearchResultProvider>() {
@Override public int compare(@Nullable QuerySearchResultProvider o1, @Nullable QuerySearchResultProvider o2) {
@ -69,8 +71,16 @@ public class SearchPhaseController {
private final FacetProcessors facetProcessors;
@Inject public SearchPhaseController(FacetProcessors facetProcessors) {
private final boolean optimizeSingleShard;
@Inject public SearchPhaseController(Settings settings, FacetProcessors facetProcessors) {
super(settings);
this.facetProcessors = facetProcessors;
this.optimizeSingleShard = componentSettings.getAsBoolean("optimize_single_shard", true);
}
public boolean optimizeSingleShard() {
return optimizeSingleShard;
}
public AggregatedDfs aggregateDfs(Iterable<DfsSearchResult> results) {
@ -90,6 +100,52 @@ public class SearchPhaseController {
return EMPTY;
}
if (optimizeSingleShard) {
boolean canOptimize = false;
QuerySearchResult result = null;
if (results1.size() == 1) {
canOptimize = true;
result = results1.iterator().next().queryResult();
} else {
// lets see if we only got hits from a single shard, if so, we can optimize...
for (QuerySearchResultProvider queryResult : results1) {
if (queryResult.queryResult().topDocs().scoreDocs.length > 0) {
if (result != null) { // we already have one, can't really optimize
canOptimize = false;
break;
}
canOptimize = true;
result = queryResult.queryResult();
}
}
}
if (canOptimize) {
ScoreDoc[] scoreDocs = result.topDocs().scoreDocs;
if (scoreDocs.length < result.from()) {
return EMPTY;
}
int resultDocsSize = result.size();
if ((scoreDocs.length - result.from()) < resultDocsSize) {
resultDocsSize = scoreDocs.length - result.from();
}
if (result.topDocs() instanceof TopFieldDocs) {
ShardDoc[] docs = new ShardDoc[resultDocsSize];
for (int i = 0; i < resultDocsSize; i++) {
ScoreDoc scoreDoc = scoreDocs[result.from() + i];
docs[i] = new ShardFieldDoc(result.shardTarget(), scoreDoc.doc, scoreDoc.score, ((FieldDoc) scoreDoc).fields);
}
return docs;
} else {
ShardDoc[] docs = new ShardDoc[resultDocsSize];
for (int i = 0; i < resultDocsSize; i++) {
ScoreDoc scoreDoc = scoreDocs[result.from() + i];
docs[i] = new ShardScoreDoc(result.shardTarget(), scoreDoc.doc, scoreDoc.score);
}
return docs;
}
}
}
List<? extends QuerySearchResultProvider> results = QUERY_RESULT_ORDERING.sortedCopy(results1);
QuerySearchResultProvider queryResultProvider = results.get(0);

View File

@ -66,7 +66,12 @@ public class SingleShardEmbeddedSearchTests extends AbstractNodesTests {
private Client client;
protected boolean optimizeSingleShard() {
return true;
}
@BeforeClass public void createNodeAndInitWithData() throws Exception {
putDefaultSettings(settingsBuilder().put("search.controller.optimize_single_shard", optimizeSingleShard()));
startNode("server1");
client = client("server1");
@ -89,6 +94,10 @@ public class SingleShardEmbeddedSearchTests extends AbstractNodesTests {
closeAllNodes();
}
@Test public void verifyOptimizeSingleShardSetting() {
assertThat(searchPhaseController.optimizeSingleShard(), equalTo(optimizeSingleShard()));
}
@Test public void testDirectDfs() throws Exception {
DfsSearchResult dfsResult = searchService.executeDfsPhase(searchRequest(searchSource().query(termQuery("name", "test1"))));

View File

@ -0,0 +1,27 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.integration.search.embedded;
public class SingleShardNoOptimizationEmbeddedSearchTests extends SingleShardEmbeddedSearchTests {
@Override protected boolean optimizeSingleShard() {
return false;
}
}