Skip to content

Commit bcb9f14

Browse files
weiwang19wwang30mkhludnev
authored
SOLR-17058: Request param to disable distributed stats request at query time (#2046)
* add param to disable distrib stats at query time --------- Co-authored-by: wwang30 <[email protected]> Co-authored-by: Mikhail Khludnev <[email protected]>
1 parent e7051f9 commit bcb9f14

File tree

10 files changed

+138
-6
lines changed

10 files changed

+138
-6
lines changed

solr/CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ Improvements
100100
* SOLR-17159: bin/solr post now has proper unit testing. Users can specify a --dry-run option to
101101
simulate posting documents without sending them to Solr. (Eric Pugh)
102102

103+
* SOLR-17058: Add 'distrib.statsCache' parameter to disable distributed stats requests at query time. (Wei Wang, Mikhail Khludnev)
104+
103105
Optimizations
104106
---------------------
105107
* SOLR-17144: Close searcherExecutor thread per core after 1 minute (Pierre Salagnac, Christine Poerschke)

solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ public void prepare(ResponseBuilder rb) throws IOException {
168168
rb.setQueryString(queryString);
169169
}
170170

171+
// set the flag for distributed stats
172+
rb.setEnableDistribStats(params.getBool(CommonParams.DISTRIB_STATS_CACHE, true));
173+
171174
try {
172175
QParser parser = QParser.getParser(rb.getQueryString(), defType, req);
173176
Query q = parser.getQuery();
@@ -365,6 +368,7 @@ public void process(ResponseBuilder rb) throws IOException {
365368
QueryCommand cmd = rb.createQueryCommand();
366369
cmd.setTimeAllowed(timeAllowed);
367370
cmd.setMinExactCount(getMinExactCount(params));
371+
cmd.setEnableDistribStats(rb.isEnableDistribStats());
368372

369373
boolean isCancellableQuery = params.getBool(CommonParams.IS_QUERY_CANCELLABLE, false);
370374

@@ -736,8 +740,9 @@ protected void regularFinishStage(ResponseBuilder rb) {
736740

737741
protected void createDistributedStats(ResponseBuilder rb) {
738742
StatsCache cache = rb.req.getSearcher().getStatsCache();
739-
if ((rb.getFieldFlags() & SolrIndexSearcher.GET_SCORES) != 0
740-
|| rb.getSortSpec().includesScore()) {
743+
if (rb.isEnableDistribStats()
744+
&& ((rb.getFieldFlags() & SolrIndexSearcher.GET_SCORES) != 0
745+
|| rb.getSortSpec().includesScore())) {
741746
ShardRequest sreq = cache.retrieveStatsRequest(rb);
742747
if (sreq != null) {
743748
rb.addRequest(this, sreq);

solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ public class ResponseBuilder {
7272

7373
private boolean isCancellation;
7474
private String cancellationUUID;
75-
7675
private String taskStatusCheckUUID;
7776
private boolean isTaskListRequest;
77+
private boolean isEnableDistribStats = true;
7878

7979
private QParser qparser = null;
8080
private String queryString = null;
@@ -520,4 +520,12 @@ public void setTaskStatusCheckUUID(String taskUUID) {
520520
public String getTaskStatusCheckUUID() {
521521
return taskStatusCheckUUID;
522522
}
523+
524+
public void setEnableDistribStats(boolean isEnableDistribStats) {
525+
this.isEnableDistribStats = isEnableDistribStats;
526+
}
527+
528+
public boolean isEnableDistribStats() {
529+
return isEnableDistribStats;
530+
}
523531
}

solr/core/src/java/org/apache/solr/search/QueryCommand.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class QueryCommand {
3939
private long timeAllowed = -1;
4040
private int minExactCount = Integer.MAX_VALUE;
4141
private CursorMark cursorMark;
42+
private boolean enableDistribStats = true;
4243

4344
public CursorMark getCursorMark() {
4445
return cursorMark;
@@ -220,4 +221,12 @@ public void setQueryCancellable(boolean isQueryCancellable) {
220221
public boolean isQueryCancellable() {
221222
return isQueryCancellable;
222223
}
224+
225+
public void setEnableDistribStats(boolean enableDistribStats) {
226+
this.enableDistribStats = enableDistribStats;
227+
}
228+
229+
public boolean isEnableDistribStats() {
230+
return enableDistribStats;
231+
}
223232
}

solr/core/src/java/org/apache/solr/search/QueryResultKey.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,31 @@ public final class QueryResultKey implements Accountable {
4040
final List<Query> filters;
4141
final int nc_flags; // non-comparable flags... ignored by hashCode and equals
4242
final int minExactCount;
43-
43+
final boolean enableDistribStats;
4444
private final int hc; // cached hashCode
4545
private final long ramBytesUsed; // cached
4646

4747
public QueryResultKey(Query query, List<Query> filters, Sort sort, int nc_flags) {
48-
this(query, filters, sort, nc_flags, Integer.MAX_VALUE);
48+
this(query, filters, sort, nc_flags, Integer.MAX_VALUE, true);
4949
}
5050

5151
public QueryResultKey(
5252
Query query, List<Query> filters, Sort sort, int nc_flags, int minExactCount) {
53+
this(query, filters, sort, nc_flags, minExactCount, true);
54+
}
55+
56+
public QueryResultKey(
57+
Query query,
58+
List<Query> filters,
59+
Sort sort,
60+
int nc_flags,
61+
int minExactCount,
62+
boolean enableDistribStats) {
5363
this.query = query;
5464
this.sort = sort;
5565
this.nc_flags = nc_flags;
5666
this.minExactCount = minExactCount;
67+
this.enableDistribStats = enableDistribStats;
5768

5869
int h = query.hashCode();
5970

@@ -113,6 +124,7 @@ public boolean equals(Object o) {
113124
if (!this.query.equals(other.query)) return false;
114125
if (!unorderedCompare(this.filters, other.filters)) return false;
115126
if (this.minExactCount != other.minExactCount) return false;
127+
if (this.enableDistribStats != other.enableDistribStats) return false;
116128

117129
for (int i = 0; i < sfields.size(); i++) {
118130
SortField sf1 = this.sfields.get(i);

solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,13 @@ private void getDocListC(QueryResult qr, QueryCommand cmd) throws IOException {
15661566
// all the current flags can be reused during warming,
15671567
// so set all of them on the cache key.
15681568
key =
1569-
new QueryResultKey(q, cmd.getFilterList(), cmd.getSort(), flags, cmd.getMinExactCount());
1569+
new QueryResultKey(
1570+
q,
1571+
cmd.getFilterList(),
1572+
cmd.getSort(),
1573+
flags,
1574+
cmd.getMinExactCount(),
1575+
cmd.isEnableDistribStats());
15701576
if ((flags & NO_CHECK_QCACHE) == 0) {
15711577
superset = queryResultCache.get(key);
15721578

solr/core/src/test/org/apache/solr/core/QueryResultKeyTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ public void testMinExactCount() {
210210
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0));
211211
}
212212

213+
public void testDisableDistribStats() {
214+
int[] nums = smallArrayOfRandomNumbers();
215+
final Query base = new FlatHashTermQuery("base");
216+
assertKeyEquals(
217+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, Integer.MAX_VALUE, true),
218+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0));
219+
assertKeyEquals(
220+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, 10, true),
221+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, 10));
222+
assertKeyNotEquals(
223+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, Integer.MAX_VALUE, false),
224+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0));
225+
assertKeyNotEquals(
226+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, 20, false),
227+
new QueryResultKey(base, buildFiltersFromNumbers(nums), null, 0, 20));
228+
}
229+
213230
/** does bi-directional equality check as well as verifying hashCode */
214231
public void assertKeyEquals(QueryResultKey key1, QueryResultKey key2) {
215232
assertNotNull(key1);

solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
import org.apache.solr.common.SolrInputDocument;
3232
import org.apache.solr.common.cloud.CompositeIdRouter;
3333
import org.apache.solr.common.cloud.ImplicitDocRouter;
34+
import org.apache.solr.common.params.CommonParams;
3435
import org.apache.solr.common.params.ShardParams;
36+
import org.apache.solr.common.util.NamedList;
3537
import org.apache.solr.embedded.JettySolrRunner;
3638
import org.junit.Test;
3739
import org.slf4j.Logger;
@@ -263,4 +265,55 @@ private void addDocsRandomly() throws IOException, SolrServerException {
263265
solrCluster.getSolrClient().commit("collection1_local");
264266
solrCluster.getSolrClient().commit("collection2_local");
265267
}
268+
269+
@Test
270+
@SuppressWarnings("unchecked")
271+
public void testDisableDistribStats() throws Exception {
272+
273+
// single collection with implicit router
274+
final String COLLECTION = "collection1";
275+
createCollection(COLLECTION, "conf1", ImplicitDocRouter.NAME);
276+
SolrClient client = solrCluster.getSolrClient();
277+
278+
SolrInputDocument doc = new SolrInputDocument();
279+
doc.setField("id", "1");
280+
doc.setField("cat", "tv");
281+
doc.addField(ShardParams._ROUTE_, "a");
282+
client.add(COLLECTION, doc);
283+
284+
doc = new SolrInputDocument();
285+
doc.setField("id", "2");
286+
doc.setField("cat", "ipad");
287+
doc.addField(ShardParams._ROUTE_, "b");
288+
client.add(COLLECTION, doc);
289+
290+
client.commit(COLLECTION);
291+
// distributed stats implicitly enabled by default
292+
SolrQuery query =
293+
new SolrQuery(
294+
"q", "cat:tv",
295+
"fl", "id,score",
296+
"debug", "track");
297+
QueryResponse rsp = client.query(COLLECTION, query);
298+
NamedList<Object> track = (NamedList<Object>) rsp.getDebugMap().get("track");
299+
assertNotNull(track);
300+
assertNotNull("stats cache hit", track.get("PARSE_QUERY"));
301+
302+
// distributed stats explicitly disabled
303+
query.set(CommonParams.DISTRIB_STATS_CACHE, "false");
304+
query.set(CommonParams.Q, "{!terms f=id}1,2");
305+
rsp = client.query(COLLECTION, query);
306+
track = (NamedList<Object>) rsp.getDebugMap().get("track");
307+
assertNotNull(track);
308+
assertNull("NO stats cache hit", track.get("PARSE_QUERY"));
309+
assertNotNull("just search", track.get("EXECUTE_QUERY"));
310+
311+
// distributed stats explicitly enabled
312+
query.set(CommonParams.DISTRIB_STATS_CACHE, "true");
313+
query.set(CommonParams.Q, "cat:electronics");
314+
rsp = client.query(COLLECTION, query);
315+
track = (NamedList<Object>) rsp.getDebugMap().get("track");
316+
assertNotNull(track);
317+
assertNotNull("stats cache hit", track.get("PARSE_QUERY"));
318+
}
266319
}

solr/solr-ref-guide/modules/deployment-guide/pages/solrcloud-distributed-requests.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,17 @@ For example, the following line makes Solr use the `ExactStatsCache` implementat
447447
<statsCache class="org.apache.solr.search.stats.ExactStatsCache"/>
448448
----
449449

450+
=== distrib.statsCache Parameter
451+
452+
The query param distrib.statsCache defaults to `true`. If set to `false`, distributed calls to fetch global term stats is turned off for this query. This can reduce overhead for queries that do not utilize distributed IDF for score calculation.
453+
454+
[source,xml]
455+
----
456+
http://localhost:8987/solr/collection1/select?q=*%3A*&wt=json&fq={!terms f=id}id1,id2&distrib.statsCache=false
457+
----
458+
459+
460+
450461
== Avoiding Distributed Deadlock
451462

452463
Each shard serves top-level query requests and then makes sub-requests to all of the other shards.

solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,15 @@ public static EchoParamStyle get(String v) {
295295
@Deprecated(since = "9.4")
296296
String DISABLE_REQUEST_ID = "disableRequestId";
297297

298+
/**
299+
* Parameter to control the distributed term statistics request for current query when distributed
300+
* IDF is enabled in solrconfig
301+
*
302+
* <p>Defaults to 'true' if not specified. Distributed stats request will be disabled by setting
303+
* to 'false'
304+
*/
305+
String DISTRIB_STATS_CACHE = "distrib.statsCache";
306+
298307
/** Request Purpose parameter added to each internal shard request when using debug=track */
299308
String REQUEST_PURPOSE = "requestPurpose";
300309

0 commit comments

Comments
 (0)