88import static org .opensearch .core .xcontent .DeprecationHandler .IGNORE_DEPRECATIONS ;
99import static org .opensearch .search .sort .FieldSortBuilder .DOC_FIELD_NAME ;
1010import static org .opensearch .search .sort .SortOrder .ASC ;
11+ import static org .opensearch .sql .opensearch .storage .OpenSearchIndex .METADATA_FIELD_ID ;
1112
1213import java .io .IOException ;
1314import java .util .Collections ;
3839import org .opensearch .search .aggregations .bucket .composite .InternalComposite ;
3940import org .opensearch .search .builder .PointInTimeBuilder ;
4041import org .opensearch .search .builder .SearchSourceBuilder ;
41- import org .opensearch .search .sort .FieldSortBuilder ;
42- import org .opensearch .search .sort .SortBuilders ;
42+ import org .opensearch .sql .monitor .profile .MetricName ;
43+ import org .opensearch .sql .monitor .profile .ProfileMetric ;
44+ import org .opensearch .sql .monitor .profile .QueryProfiling ;
4345import org .opensearch .sql .opensearch .data .value .OpenSearchExprValueFactory ;
4446import org .opensearch .sql .opensearch .response .OpenSearchResponse ;
4547import org .opensearch .sql .opensearch .storage .OpenSearchIndex ;
5658@ ToString
5759public class OpenSearchQueryRequest implements OpenSearchRequest {
5860 private static final Logger LOG = LogManager .getLogger ();
59- private static final String SHARD_DOC_FIELD_NAME = "_shard_doc" ;
6061
6162 /** {@link OpenSearchRequest.IndexName}. */
6263 private final IndexName indexName ;
@@ -206,6 +207,8 @@ private OpenSearchResponse search(Function<SearchRequest, SearchResponse> search
206207 new OpenSearchResponse (
207208 SearchHits .empty (), exprValueFactory , includes , isCountAggRequest ());
208209 } else {
210+ ProfileMetric metric = QueryProfiling .current ().getOrCreateMetric (MetricName .EXECUTE );
211+ long executionStartTime = System .nanoTime ();
209212 // Set afterKey to request, null for first round (afterKey is null in the beginning).
210213 if (this .sourceBuilder .aggregations () != null ) {
211214 this .sourceBuilder .aggregations ().getAggregatorFactories ().stream ()
@@ -238,6 +241,7 @@ private OpenSearchResponse search(Function<SearchRequest, SearchResponse> search
238241 searchDone = true ;
239242 }
240243 needClean = searchDone ;
244+ metric .add (System .nanoTime () - executionStartTime );
241245 }
242246 return openSearchResponse ;
243247 }
@@ -249,35 +253,20 @@ public OpenSearchResponse searchWithPIT(Function<SearchRequest, SearchResponse>
249253 new OpenSearchResponse (
250254 SearchHits .empty (), exprValueFactory , includes , isCountAggRequest ());
251255 } else {
256+ ProfileMetric metric = QueryProfiling .current ().getOrCreateMetric (MetricName .EXECUTE );
257+ long executionStartTime = System .nanoTime ();
252258 this .sourceBuilder .pointInTimeBuilder (new PointInTimeBuilder (this .pitId ));
253259 this .sourceBuilder .timeout (cursorKeepAlive );
254260 // check for search after
255261 if (searchAfter != null ) {
256262 this .sourceBuilder .searchAfter (searchAfter );
257263 }
258- // Add sort tiebreaker for PIT search.
259- // We cannot remove it since `_shard_doc` is not added implicitly in PIT now.
260- // Ref https://github.com/opensearch-project/OpenSearch/pull/18924#issuecomment-3342365950
261- if (this .sourceBuilder .sorts () == null || this .sourceBuilder .sorts ().isEmpty ()) {
262- // If no sort field specified, sort by `_doc` + `_shard_doc`to get better performance
264+ // Set sort field for search_after
265+ if (this .sourceBuilder .sorts () == null ) {
263266 this .sourceBuilder .sort (DOC_FIELD_NAME , ASC );
264- this .sourceBuilder .sort (SortBuilders .fieldSort (SHARD_DOC_FIELD_NAME ));
265- } else {
266- // If sort fields specified, sort by `fields` + `_doc` + `_shard_doc`.
267- if (this .sourceBuilder .sorts ().stream ()
268- .noneMatch (
269- b ->
270- b instanceof FieldSortBuilder
271- && ((FieldSortBuilder ) b ).fieldName ().equals (DOC_FIELD_NAME ))) {
272- this .sourceBuilder .sort (DOC_FIELD_NAME , ASC );
273- }
274- if (this .sourceBuilder .sorts ().stream ()
275- .noneMatch (
276- b ->
277- b instanceof FieldSortBuilder
278- && SHARD_DOC_FIELD_NAME .equals (((FieldSortBuilder ) b ).fieldName ()))) {
279- this .sourceBuilder .sort (SortBuilders .fieldSort (SHARD_DOC_FIELD_NAME ));
280- }
267+ // Workaround to preserve sort location more exactly,
268+ // see https://github.com/opensearch-project/sql/pull/3061
269+ this .sourceBuilder .sort (METADATA_FIELD_ID , ASC );
281270 }
282271 SearchRequest searchRequest =
283272 new SearchRequest ().indices (indexName .getIndexNames ()).source (this .sourceBuilder );
@@ -297,6 +286,7 @@ public OpenSearchResponse searchWithPIT(Function<SearchRequest, SearchResponse>
297286 LOG .debug (sourceBuilder );
298287 }
299288 }
289+ metric .add (System .nanoTime () - executionStartTime );
300290 }
301291 return openSearchResponse ;
302292 }
0 commit comments