forked from elastic/built-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_profiling_queries.html
786 lines (762 loc) · 34.3 KB
/
_profiling_queries.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Profiling Queries | Elasticsearch Guide [6.3] | Elastic</title>
<meta class="elastic" name="content" content="Profiling Queries | Elasticsearch Guide [6.3]">
<link rel="home" href="index.html" title="Elasticsearch Guide [6.3]"/>
<link rel="up" href="search-profile.html" title="Profile API"/>
<link rel="prev" href="search-profile.html" title="Profile API"/>
<link rel="next" href="_profiling_aggregations.html" title="Profiling Aggregations"/>
<meta class="elastic" name="product_version" content="6.3"/>
<meta class="elastic" name="product_name" content="Elasticsearch"/>
<meta class="elastic" name="website_area" content="documentation"/>
<meta name="DC.type" content="Learn/Docs/Elasticsearch/Reference/6.3"/>
<meta name="DC.subject" content="Elasticsearch"/>
<meta name="DC.identifier" content="6.3"/>
<meta name="robots" content="noindex,nofollow"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.optimizely.com/js/18132920325.js"></script>
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-title" content="Elastic">
<meta name="application-name" content="Elastic">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd" />
<meta name="yandex-verification" content="d8a47e95d0972434" />
<meta name="localized" content="true" />
<meta name="st:robots" content="follow,index" />
<meta property="og:image" content="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt280217a63b82a734/6202d3378b1f312528798412/elastic-logo.svg" />
<meta property="og:image:width" content="500" />
<meta property="og:image:height" content="172" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
<link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
<link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
<!-- Give IE8 a fighting chance -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link rel="stylesheet" type="text/css" href="/guide/static/styles.css" />
</head>
<!--© 2015-2022 Elasticsearch B.V. -->
<!-- All Elastic documentation is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. -->
<!-- http://creativecommons.org/licenses/by-nc-nd/4.0/ -->
<body>
<!-- Google Tag Manager -->
<script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
<!-- End Google Tag Manager -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-12395217-16');
</script>
<!-- Google Tag Manager for GA4 -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KNJMG2M');</script>
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KNJMG2M" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager for GA4-->
<div id='elastic-nav' style="display:none;"></div>
<script src='https://www.elastic.co/elastic-nav.js'></script>
<div class="main-container">
<section id="content" >
<div class="content-wrapper">
<section id="guide" lang="en">
<div class="container-fluid">
<div class="row pb-3">
<div class="col-12 order-2 col-md-4 order-md-1 col-lg-3 h-almost-full-md sticky-top-md" id="left_col">
<!-- The TOC is appended here -->
</div>
<div class="col-12 order-1 col-md-8 order-md-2 col-lg-7 order-lg-2 guide-section" id="middle_col">
<!-- start body -->
<div class="page_header">
<strong>IMPORTANT</strong>: No additional bug fixes or documentation updates
will be released for this version. For the latest information, see the
<a href="../current/index.html">current release documentation</a>.
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="/guide/">Elastic Docs</a></span>
<span class="chevron-right">›</span><span class="breadcrumb-link"><a href="index.html">Elasticsearch Guide [6.3]</a></span>
<span class="chevron-right">›</span><span class="breadcrumb-link"><a href="search.html">Search APIs</a></span>
<span class="chevron-right">›</span><span class="breadcrumb-link"><a href="search-profile.html">Profile API</a></span>
</div>
<div class="navheader">
<span class="prev">
<a href="search-profile.html">« Profile API</a>
</span>
<span class="next">
<a href="_profiling_aggregations.html">Profiling Aggregations »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title"><a id="_profiling_queries"></a>Profiling Queries<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h2>
</div></div></div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>The details provided by the Profile API directly expose Lucene class names and concepts, which means
that complete interpretation of the results require fairly advanced knowledge of Lucene. This
page attempts to give a crash-course in how Lucene executes queries so that you can use the Profile API to successfully
diagnose and debug queries, but it is only an overview. For complete understanding, please refer
to Lucene’s documentation and, in places, the code.</p>
<p>With that said, a complete understanding is often not required to fix a slow query. It is usually
sufficient to see that a particular component of a query is slow, and not necessarily understand why
the <code class="literal">advance</code> phase of that query is the cause, for example.</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="profile-query-section"></a><code class="literal">query</code> Section<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h3>
</div></div></div>
<p>The <code class="literal">query</code> section contains detailed timing of the query tree executed by Lucene on a particular shard.
The overall structure of this query tree will resemble your original Elasticsearch query, but may be slightly
(or sometimes very) different. It will also use similar but not always identical naming. Using our previous
<code class="literal">match</code> query example, let’s analyze the <code class="literal">query</code> section:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"query": [
{
"type": "BooleanQuery",
"description": "message:some message:number",
"time_in_nanos": "1873811",
"breakdown": {...}, <a id="CO48-1"></a><i class="conum" data-value="1"></i>
"children": [
{
"type": "TermQuery",
"description": "message:some",
"time_in_nanos": "391943",
"breakdown": {...}
},
{
"type": "TermQuery",
"description": "message:number",
"time_in_nanos": "210682",
"breakdown": {...}
}
]
}
]</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO48-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>The breakdown timings are omitted for simplicity</p>
</td>
</tr>
</table>
</div>
<p>Based on the profile structure, we can see that our <code class="literal">match</code> query was rewritten by Lucene into a BooleanQuery with two
clauses (both holding a TermQuery). The <code class="literal">type</code> field displays the Lucene class name, and often aligns with
the equivalent name in Elasticsearch. The <code class="literal">description</code> field displays the Lucene explanation text for the query, and
is made available to help differentiating between parts of your query (e.g. both <code class="literal">message:search</code> and <code class="literal">message:test</code>
are TermQuery’s and would appear identical otherwise.</p>
<p>The <code class="literal">time_in_nanos</code> field shows that this query took ~1.8ms for the entire BooleanQuery to execute. The recorded time is inclusive
of all children.</p>
<p>The <code class="literal">breakdown</code> field will give detailed stats about how the time was spent, we’ll look at
that in a moment. Finally, the <code class="literal">children</code> array lists any sub-queries that may be present. Because we searched for two
values ("search test"), our BooleanQuery holds two children TermQueries. They have identical information (type, time,
breakdown, etc). Children are allowed to have their own children.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_timing_breakdown"></a>Timing Breakdown<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h4>
</div></div></div>
<p>The <code class="literal">breakdown</code> component lists detailed timing statistics about low-level Lucene execution:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"breakdown": {
"score": 51306,
"score_count": 4,
"build_scorer": 2935582,
"build_scorer_count": 1,
"match": 0,
"match_count": 0,
"create_weight": 919297,
"create_weight_count": 1,
"next_doc": 53876,
"next_doc_count": 5,
"advance": 0,
"advance_count": 0
}</pre>
</div>
<p>Timings are listed in wall-clock nanoseconds and are not normalized at all. All caveats about the overall
<code class="literal">time_in_nanos</code> apply here. The intention of the breakdown is to give you a feel for A) what machinery in Lucene is
actually eating time, and B) the magnitude of differences in times between the various components. Like the overall time,
the breakdown is inclusive of all children times.</p>
<p>The meaning of the stats are as follows:</p>
<h4><a id="_all_parameters_3"></a>All parameters:<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h4>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col/>
<col/>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">create_weight</code>
</p>
</td>
<td valign="top">
<p>
A Query in Lucene must be capable of reuse across multiple IndexSearchers (think of it as the engine that
executes a search against a specific Lucene Index). This puts Lucene in a tricky spot, since many queries
need to accumulate temporary state/statistics associated with the index it is being used against, but the
Query contract mandates that it must be immutable.
<br>
<br>
To get around this, Lucene asks each query to generate a Weight object which acts as a temporary context
object to hold state associated with this particular (IndexSearcher, Query) tuple. The <code class="literal">weight</code> metric
shows how long this process takes
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">build_scorer</code>
</p>
</td>
<td valign="top">
<p>
This parameter shows how long it takes to build a Scorer for the query. A Scorer is the mechanism that
iterates over matching documents generates a score per-document (e.g. how well does "foo" match the document?).
Note, this records the time required to generate the Scorer object, not actually score the documents. Some
queries have faster or slower initialization of the Scorer, depending on optimizations, complexity, etc.
<br>
<br>
This may also showing timing associated with caching, if enabled and/or applicable for the query
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">next_doc</code>
</p>
</td>
<td valign="top">
<p>
The Lucene method <code class="literal">next_doc</code> returns Doc ID of the next document matching the query. This statistic shows
the time it takes to determine which document is the next match, a process that varies considerably depending
on the nature of the query. Next_doc is a specialized form of advance() which is more convenient for many
queries in Lucene. It is equivalent to advance(docId() + 1)
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">advance</code>
</p>
</td>
<td valign="top">
<p>
<code class="literal">advance</code> is the "lower level" version of next_doc: it serves the same purpose of finding the next matching
doc, but requires the calling query to perform extra tasks such as identifying and moving past skips, etc.
However, not all queries can use next_doc, so <code class="literal">advance</code> is also timed for those queries.
<br>
<br>
Conjunctions (e.g. <code class="literal">must</code> clauses in a boolean) are typical consumers of <code class="literal">advance</code>
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">matches</code>
</p>
</td>
<td valign="top">
<p>
Some queries, such as phrase queries, match documents using a "Two Phase" process. First, the document is
"approximately" matched, and if it matches approximately, it is checked a second time with a more rigorous
(and expensive) process. The second phase verification is what the <code class="literal">matches</code> statistic measures.
<br>
<br>
For example, a phrase query first checks a document approximately by ensuring all terms in the phrase are
present in the doc. If all the terms are present, it then executes the second phase verification to ensure
the terms are in-order to form the phrase, which is relatively more expensive than just checking for presence
of the terms.
<br>
<br>
Because this two-phase process is only used by a handful of queries, the <code class="literal">metric</code> statistic will often be zero
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">score</code>
</p>
</td>
<td valign="top">
<p>
This records the time taken to score a particular document via it’s Scorer
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">*_count</code>
</p>
</td>
<td valign="top">
<p>
Records the number of invocations of the particular method. For example, <code class="literal">"next_doc_count": 2,</code>
means the <code class="literal">nextDoc()</code> method was called on two different documents. This can be used to help judge
how selective queries are, by comparing counts between different query components.
</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="profile-collectors-section"></a><code class="literal">collectors</code> Section<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h3>
</div></div></div>
<p>The Collectors portion of the response shows high-level execution details. Lucene works by defining a "Collector"
which is responsible for coordinating the traversal, scoring and collection of matching documents. Collectors
are also how a single query can record aggregation results, execute unscoped "global" queries, execute post-query
filters, etc.</p>
<p>Looking at the previous example:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">"collector": [
{
"name": "CancellableCollector",
"reason": "search_cancelled",
"time_in_nanos": "304311",
"children": [
{
"name": "SimpleTopScoreDocCollector",
"reason": "search_top_hits",
"time_in_nanos": "32273"
}
]
}
]</pre>
</div>
<p>We see a single collector named <code class="literal">SimpleTopScoreDocCollector</code> wrapped into <code class="literal">CancellableCollector</code>. <code class="literal">SimpleTopScoreDocCollector</code> is the default "scoring and sorting"
<code class="literal">Collector</code> used by Elasticsearch. The <code class="literal">reason</code> field attempts to give a plain english description of the class name. The
<code class="literal">time_in_nanos</code> is similar to the time in the Query tree: a wall-clock time inclusive of all children. Similarly, <code class="literal">children</code> lists
all sub-collectors. The <code class="literal">CancellableCollector</code> that wraps <code class="literal">SimpleTopScoreDocCollector</code> is used by Elasticsearch to detect if the current
search was cancelled and stop collecting documents as soon as it occurs.</p>
<p>It should be noted that Collector times are <span class="strong strong"><strong>independent</strong></span> from the Query times. They are calculated, combined
and normalized independently! Due to the nature of Lucene’s execution, it is impossible to "merge" the times
from the Collectors into the Query section, so they are displayed in separate portions.</p>
<p>For reference, the various collector reason’s are:</p>
<div class="informaltable">
<table border="0" cellpadding="4px">
<colgroup>
<col/>
<col/>
</colgroup>
<tbody valign="top">
<tr>
<td valign="top">
<p>
<code class="literal">search_sorted</code>
</p>
</td>
<td valign="top">
<p>
A collector that scores and sorts documents. This is the most common collector and will be seen in most
simple searches
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">search_count</code>
</p>
</td>
<td valign="top">
<p>
A collector that only counts the number of documents that match the query, but does not fetch the source.
This is seen when <code class="literal">size: 0</code> is specified
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">search_terminate_after_count</code>
</p>
</td>
<td valign="top">
<p>
A collector that terminates search execution after <code class="literal">n</code> matching documents have been found. This is seen
when the <code class="literal">terminate_after_count</code> query parameter has been specified
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">search_min_score</code>
</p>
</td>
<td valign="top">
<p>
A collector that only returns matching documents that have a score greater than <code class="literal">n</code>. This is seen when
the top-level parameter <code class="literal">min_score</code> has been specified.
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">search_multi</code>
</p>
</td>
<td valign="top">
<p>
A collector that wraps several other collectors. This is seen when combinations of search, aggregations,
global aggs and post_filters are combined in a single search.
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">search_timeout</code>
</p>
</td>
<td valign="top">
<p>
A collector that halts execution after a specified period of time. This is seen when a <code class="literal">timeout</code> top-level
parameter has been specified.
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">aggregation</code>
</p>
</td>
<td valign="top">
<p>
A collector that Elasticsearch uses to run aggregations against the query scope. A single <code class="literal">aggregation</code>
collector is used to collect documents for <span class="strong strong"><strong>all</strong></span> aggregations, so you will see a list of aggregations
in the name rather.
</p>
</td>
</tr>
<tr>
<td valign="top">
<p>
<code class="literal">global_aggregation</code>
</p>
</td>
<td valign="top">
<p>
A collector that executes an aggregation against the global query scope, rather than the specified query.
Because the global scope is necessarily different from the executed query, it must execute it’s own
match_all query (which you will see added to the Query section) to collect your entire dataset
</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="rewrite-section"></a><code class="literal">rewrite</code> Section<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h3>
</div></div></div>
<p>All queries in Lucene undergo a "rewriting" process. A query (and its sub-queries) may be rewritten one or
more times, and the process continues until the query stops changing. This process allows Lucene to perform
optimizations, such as removing redundant clauses, replacing one query for a more efficient execution path,
etc. For example a Boolean → Boolean → TermQuery can be rewritten to a TermQuery, because all the Booleans
are unnecessary in this case.</p>
<p>The rewriting process is complex and difficult to display, since queries can change drastically. Rather than
showing the intermediate results, the total rewrite time is simply displayed as a value (in nanoseconds). This
value is cumulative and contains the total time for all queries being rewritten.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_a_more_complex_example"></a>A more complex example<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h3>
</div></div></div>
<p>To demonstrate a slightly more complex query and the associated results, we can profile the following query:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /twitter/_search
{
"profile": true,
"query": {
"term": {
"user": {
"value": "test"
}
}
},
"aggs": {
"my_scoped_agg": {
"terms": {
"field": "likes"
}
},
"my_global_agg": {
"global": {},
"aggs": {
"my_level_agg": {
"terms": {
"field": "likes"
}
}
}
}
},
"post_filter": {
"match": {
"message": "some"
}
}
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/345.console"></div>
<p>This example has:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
A query
</li>
<li class="listitem">
A scoped aggregation
</li>
<li class="listitem">
A global aggregation
</li>
<li class="listitem">
A post_filter
</li>
</ul>
</div>
<p>And the response:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
...
"profile": {
"shards": [
{
"id": "[P6-vulHtQRWuD4YnubWb7A][test][0]",
"searches": [
{
"query": [
{
"type": "TermQuery",
"description": "message:some",
"time_in_nanos": "409456",
"breakdown": {
"score": 0,
"build_scorer_count": 1,
"match_count": 0,
"create_weight": 31584,
"next_doc": 0,
"match": 0,
"create_weight_count": 1,
"next_doc_count": 2,
"score_count": 1,
"build_scorer": 377872,
"advance": 0,
"advance_count": 0
}
},
{
"type": "TermQuery",
"description": "user:test",
"time_in_nanos": "303702",
"breakdown": {
"score": 0,
"build_scorer_count": 1,
"match_count": 0,
"create_weight": 185215,
"next_doc": 5936,
"match": 0,
"create_weight_count": 1,
"next_doc_count": 2,
"score_count": 1,
"build_scorer": 112551,
"advance": 0,
"advance_count": 0
}
}
],
"rewrite_time": 7208,
"collector": [
{
"name": "CancellableCollector",
"reason": "search_cancelled",
"time_in_nanos": 2390,
"children": [
{
"name": "MultiCollector",
"reason": "search_multi",
"time_in_nanos": 1820,
"children": [
{
"name": "FilteredCollector",
"reason": "search_post_filter",
"time_in_nanos": 7735,
"children": [
{
"name": "SimpleTopScoreDocCollector",
"reason": "search_top_hits",
"time_in_nanos": 1328
}
]
},
{
"name": "BucketCollector: [[my_scoped_agg, my_global_agg]]",
"reason": "aggregation",
"time_in_nanos": 8273
}
]
}
]
}
]
}
],
"aggregations": [...] <a id="CO49-1"></a><i class="conum" data-value="1"></i>
}
]
}
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO49-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>The ``"aggregations"` portion has been omitted because it will be covered in the next section</p>
</td>
</tr>
</table>
</div>
<p>As you can see, the output is significantly verbose from before. All the major portions of the query are
represented:</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
The first <code class="literal">TermQuery</code> (user:test) represents the main <code class="literal">term</code> query
</li>
<li class="listitem">
The second <code class="literal">TermQuery</code> (message:some) represents the <code class="literal">post_filter</code> query
</li>
</ol>
</div>
<p>The Collector tree is fairly straightforward, showing how a single CancellableCollector wraps a MultiCollector
which also wraps a FilteredCollector to execute the post_filter (and in turn wraps the normal scoring SimpleCollector),
a BucketCollector to run all scoped aggregations.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_understanding_multitermquery_output"></a>Understanding MultiTermQuery output<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/6.3/docs/reference/search/profile.asciidoc">edit</a></h3>
</div></div></div>
<p>A special note needs to be made about the <code class="literal">MultiTermQuery</code> class of queries. This includes wildcards, regex and fuzzy
queries. These queries emit very verbose responses, and are not overly structured.</p>
<p>Essentially, these queries rewrite themselves on a per-segment basis. If you imagine the wildcard query <code class="literal">b*</code>, it technically
can match any token that begins with the letter "b". It would be impossible to enumerate all possible combinations,
so Lucene rewrites the query in context of the segment being evaluated. E.g. one segment may contain the tokens
<code class="literal">[bar, baz]</code>, so the query rewrites to a BooleanQuery combination of "bar" and "baz". Another segment may only have the
token <code class="literal">[bakery]</code>, so query rewrites to a single TermQuery for "bakery".</p>
<p>Due to this dynamic, per-segment rewriting, the clean tree structure becomes distorted and no longer follows a clean
"lineage" showing how one query rewrites into the next. At present time, all we can do is apologize, and suggest you
collapse the details for that query’s children if it is too confusing. Luckily, all the timing statistics are correct,
just not the physical layout in the response, so it is sufficient to just analyze the top-level MultiTermQuery and
ignore its children if you find the details too tricky to interpret.</p>
<p>Hopefully this will be fixed in future iterations, but it is a tricky problem to solve and still in-progress :)</p>
</div>
</div>
<div class="navfooter">
<span class="prev">
<a href="search-profile.html">« Profile API</a>
</span>
<span class="next">
<a href="_profiling_aggregations.html">Profiling Aggregations »</a>
</span>
</div>
</div>
<!-- end body -->
</div>
<div class="col-12 order-3 col-lg-2 order-lg-3 h-almost-full-lg sticky-top-lg" id="right_col">
<div id="sticky_content">
<!-- The OTP is appended here -->
<div class="row">
<div class="col-0 col-md-4 col-lg-0" id="bottom_left_col"></div>
<div class="col-12 col-md-8 col-lg-12">
<div id="rtpcontainer">
<div class="mktg-promo" id="most-popular">
<p class="aside-heading">Most Popular</p>
<div class="pb-2">
<p class="media-type">Video</p>
<a href="https://www.elastic.co/webinars/getting-started-elasticsearch?page=docs&placement=top-video">
<p class="mb-0">Get Started with Elasticsearch</p>
</a>
</div>
<div class="pb-2">
<p class="media-type">Video</p>
<a href="https://www.elastic.co/webinars/getting-started-kibana?page=docs&placement=top-video">
<p class="mb-0">Intro to Kibana</p>
</a>
</div>
<div class="pb-2">
<p class="media-type">Video</p>
<a href="https://www.elastic.co/webinars/introduction-elk-stack?page=docs&placement=top-video">
<p class="mb-0">ELK for Logs & Metrics</p>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<div id='elastic-footer'></div>
<script src='https://www.elastic.co/elastic-footer.js'></script>
<!-- Footer Section end-->
</section>
</div>
<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
window.initial_state = {}</script>
</body>
</html>