Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time Ordering On Scans #7133

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
10e57d5
Moved Scan Builder to Druids class and started on Scan Benchmark setup
justinborromeo Feb 1, 2019
dba6e49
Merge branch 'master' into 6088-Create-Scan-Benchmark
justinborromeo Feb 1, 2019
dd4ec1a
Need to form queries
justinborromeo Feb 1, 2019
26930f8
It runs.
justinborromeo Feb 2, 2019
7a6080f
Stuff for time-ordered scan query
justinborromeo Feb 2, 2019
79e8319
Move ScanResultValue timestamp comparator to a separate class for tes…
justinborromeo Feb 2, 2019
7b58471
Licensing stuff
justinborromeo Feb 2, 2019
989bd2d
Merge branch '6088-Create-Scan-Benchmark' into 6088-Time-Ordering-On-…
justinborromeo Feb 4, 2019
ad731a3
Change benchmark
justinborromeo Feb 4, 2019
e66339c
Remove todos
justinborromeo Feb 4, 2019
12e51a2
Added TimestampComparator tests
justinborromeo Feb 4, 2019
432acaf
Change number of benchmark iterations
justinborromeo Feb 4, 2019
01b25ed
Added time ordering to the scan benchmark
justinborromeo Feb 4, 2019
9e6e716
Changed benchmark params
justinborromeo Feb 4, 2019
20c3664
More param changes
justinborromeo Feb 4, 2019
796083f
Benchmark param change
justinborromeo Feb 4, 2019
737a833
Made Jon's changes and removed TODOs
justinborromeo Feb 5, 2019
b7d3a49
Merge branch 'master' into 6088-Time-Ordering-On-Scans-V2
justinborromeo Feb 5, 2019
86c5eee
Broke some long lines into two lines
justinborromeo Feb 5, 2019
7deb06f
Merge branch '6088-Create-Scan-Benchmark' into 6088-Time-Ordering-On-…
justinborromeo Feb 5, 2019
d1a1793
nit
justinborromeo Feb 5, 2019
b6d4df3
Decrease segment size for less memory usage
justinborromeo Feb 6, 2019
8b7d5f5
Wrote tests for heapsort scan result values and fixed bug where iterator
justinborromeo Feb 6, 2019
4f51024
Wrote more tests for scan result value sort
justinborromeo Feb 6, 2019
60b7684
Committing a param change to kick teamcity
justinborromeo Feb 6, 2019
5edbe2a
Merge github.com:apache/incubator-druid into 6088-Create-Scan-Benchmark
justinborromeo Feb 6, 2019
148939e
Merge branch '6088-Create-Scan-Benchmark' into 6088-Time-Ordering-On-…
justinborromeo Feb 6, 2019
dfe4aa9
Fixed codestyle and forbidden API errors
justinborromeo Feb 6, 2019
10b5e0c
.
justinborromeo Feb 6, 2019
8212a21
Improved conciseness
justinborromeo Feb 6, 2019
305876a
nit
justinborromeo Feb 6, 2019
e8a4b49
Merge branch 'master' into 6088-Time-Ordering-On-Scans-V2
justinborromeo Feb 6, 2019
7e872a8
Created an error message for when someone tries to time order a result
justinborromeo Feb 6, 2019
85e72a6
Set to spaces over tabs
justinborromeo Feb 6, 2019
b2c8c77
Fixing tests WIP
justinborromeo Feb 7, 2019
b432bea
Fixed failing calcite tests
justinborromeo Feb 7, 2019
ab00ead
Kicking travis with change to benchmark param
justinborromeo Feb 7, 2019
d3b335a
added all query types to scan benchmark
justinborromeo Feb 7, 2019
2e3577c
Fixed benchmark queries
justinborromeo Feb 7, 2019
134041c
Renamed sort function
justinborromeo Feb 8, 2019
93e1636
Added javadoc on ScanResultValueTimestampComparator
justinborromeo Feb 11, 2019
5f92dd7
Unused import
justinborromeo Feb 11, 2019
f0eddee
Added more javadoc
justinborromeo Feb 11, 2019
ecb0f48
improved doc
justinborromeo Feb 11, 2019
4e69276
Removed unused import to satisfy PMD check
justinborromeo Feb 11, 2019
35150fe
Small changes
justinborromeo Feb 15, 2019
7baeade
Changes based on Gian's comments
justinborromeo Feb 20, 2019
cd489a0
Fixed failing test due to null resultFormat
justinborromeo Feb 20, 2019
c9142e7
Merge branch 'master' into 6088-Time-Ordering-On-Scans-V2
justinborromeo Feb 20, 2019
fba6b02
Added config and get # of segments
justinborromeo Feb 21, 2019
b13ff62
Set up time ordering strategy decision tree
justinborromeo Feb 21, 2019
f83e996
Refactor and pQueue works
justinborromeo Feb 22, 2019
1813a54
Cleanup
justinborromeo Feb 22, 2019
f57ff25
Ordering is correct on n-way merge -> still need to batch events into
justinborromeo Feb 22, 2019
e1fc295
WIP
justinborromeo Feb 22, 2019
023538d
Sequence stuff is so dirty :(
justinborromeo Feb 22, 2019
3b923da
Fixed bug introduced by replacing deque with list
justinborromeo Feb 22, 2019
06a5218
Wrote docs
justinborromeo Feb 23, 2019
763c43d
Multi-historical setup works
justinborromeo Feb 23, 2019
69b24bd
Merge branch 'master' into 6088-Time-Ordering-On-Scans-N-Way-Merge
justinborromeo Feb 23, 2019
451e2b4
WIP
justinborromeo Feb 26, 2019
18cce9a
Change so batching only occurs on broker for time-ordered scans
justinborromeo Feb 26, 2019
5bd0e1a
Merge branch 'master' into 6088-Time-Ordering-On-Scans-N-Way-Merge
justinborromeo Feb 27, 2019
de83b11
Fixed mistakes in merge
justinborromeo Feb 27, 2019
806166f
Fixed failing tests
justinborromeo Feb 28, 2019
5ff59f5
Reset config
justinborromeo Feb 28, 2019
47c970b
Wrote tests and added Javadoc
justinborromeo Mar 1, 2019
83ec3fe
Nit-change on javadoc
justinborromeo Mar 1, 2019
2d1978d
Merge branch 'master' into 6088-Time-Ordering-On-Scans-N-Way-Merge
justinborromeo Mar 4, 2019
35c96d3
Checkstyle fix
justinborromeo Mar 5, 2019
6dc53b3
Improved test and appeased TeamCity
justinborromeo Mar 6, 2019
fb966de
Sorry, checkstyle
justinborromeo Mar 7, 2019
73f4038
Applied Jon's recommended changes
justinborromeo Mar 8, 2019
cce917a
Checkstyle fix
justinborromeo Mar 8, 2019
45e95bb
Optimization
justinborromeo Mar 12, 2019
57b5682
Fixed tests
justinborromeo Mar 12, 2019
a032c46
Updated error message
justinborromeo Mar 12, 2019
7e49d47
Added error message for UOE
justinborromeo Mar 12, 2019
7bfa77d
Merge branch 'Update-Query-Interrupted-Exception' into 6088-Time-Orde…
justinborromeo Mar 12, 2019
2528a56
Renaming
justinborromeo Mar 18, 2019
4823dab
Finish rename
justinborromeo Mar 20, 2019
42f5246
Smarter limiting for pQueue method
justinborromeo Mar 21, 2019
43d490c
Optimized n-way merge strategy
justinborromeo Mar 21, 2019
4947216
Rename segment limit -> segment partitions limit
justinborromeo Mar 22, 2019
1b46b58
Added a bit of docs
justinborromeo Mar 22, 2019
62dceda
More comments
justinborromeo Mar 22, 2019
a87d021
Fix checkstyle and test
justinborromeo Mar 22, 2019
8b3b6b5
Nit comment
justinborromeo Mar 22, 2019
86d9730
Fixed failing tests -> allow usage of all types of segment spec
justinborromeo Mar 25, 2019
ec47028
Fixed failing tests -> allow usage of all types of segment spec
justinborromeo Mar 25, 2019
8f01d8d
Revert "Fixed failing tests -> allow usage of all types of segment spec"
justinborromeo Mar 25, 2019
57033f3
Merge branch '6088-Time-Ordering-On-Scans-N-Way-Merge' of github.com:…
justinborromeo Mar 25, 2019
b822fc7
Revert "Merge branch '6088-Time-Ordering-On-Scans-N-Way-Merge' of git…
justinborromeo Mar 25, 2019
da4fc66
Check type of segment spec before using for time ordering
justinborromeo Mar 25, 2019
219af47
Fix bug in numRowsScanned
justinborromeo Mar 25, 2019
3569268
Fix bug messing up count of rows
justinborromeo Mar 25, 2019
8a6bb11
Fix docs and flipped boolean in ScanQueryLimitRowIterator
justinborromeo Mar 26, 2019
376e8bf
Refactor n-way merge
justinborromeo Mar 26, 2019
fb858ef
Added test for n-way merge
justinborromeo Mar 26, 2019
487f31f
Refixed regression
justinborromeo Mar 26, 2019
480e932
Checkstyle and doc update
justinborromeo Mar 26, 2019
1df50de
Merge branch 'master' into 6088-Time-Ordering-On-Scans-N-Way-Merge
justinborromeo Mar 26, 2019
231a72e
Modified sequence limit to accept longs and added test for long limits
justinborromeo Mar 28, 2019
07503ea
doc fix
justinborromeo Mar 28, 2019
287a367
Implemented Clint's recommendations
justinborromeo Mar 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,15 @@ public class ScanBenchmark
@Param({"200000"})
private int rowsPerSegment;

@Param({"basic.A"})
@Param({"basic.A", "basic.B", "basic.C", "basic.D"})
private String schemaAndQuery;

@Param({"1000", "99999"})
private int limit;

@Param({"NONE", "DESCENDING", "ASCENDING"})
private static ScanQuery.Order ordering;

private static final Logger log = new Logger(ScanBenchmark.class);
private static final ObjectMapper JSON_MAPPER;
private static final IndexMergerV9 INDEX_MERGER_V9;
Expand Down Expand Up @@ -178,7 +181,8 @@ private static Druids.ScanQueryBuilder basicA(final BenchmarkSchemaInfo basicSch

return Druids.newScanQueryBuilder()
.dataSource("blah")
.intervals(intervalSpec);
.intervals(intervalSpec)
.order(ordering);
}

private static Druids.ScanQueryBuilder basicB(final BenchmarkSchemaInfo basicSchema)
Expand All @@ -197,7 +201,9 @@ private static Druids.ScanQueryBuilder basicB(final BenchmarkSchemaInfo basicSch

return Druids.newScanQueryBuilder()
.filters(filter)
.intervals(intervalSpec);
.dataSource("blah")
.intervals(intervalSpec)
.order(ordering);
}

private static Druids.ScanQueryBuilder basicC(final BenchmarkSchemaInfo basicSchema)
Expand All @@ -207,8 +213,10 @@ private static Druids.ScanQueryBuilder basicC(final BenchmarkSchemaInfo basicSch

final String dimName = "dimUniform";
return Druids.newScanQueryBuilder()
.filters(new SelectorDimFilter(dimName, "3", StrlenExtractionFn.instance()))
.intervals(intervalSpec);
.filters(new SelectorDimFilter(dimName, "3", StrlenExtractionFn.instance()))
.intervals(intervalSpec)
.dataSource("blah")
.order(ordering);
}

private static Druids.ScanQueryBuilder basicD(final BenchmarkSchemaInfo basicSchema)
Expand All @@ -220,8 +228,10 @@ private static Druids.ScanQueryBuilder basicD(final BenchmarkSchemaInfo basicSch
final String dimName = "dimUniform";

return Druids.newScanQueryBuilder()
.filters(new BoundDimFilter(dimName, "100", "10000", true, true, true, null, null))
.intervals(intervalSpec);
.filters(new BoundDimFilter(dimName, "100", "10000", true, true, true, null, null))
.intervals(intervalSpec)
.dataSource("blah")
.order(ordering);
}

@Setup
Expand Down Expand Up @@ -289,7 +299,8 @@ public void setup() throws IOException
config,
DefaultGenericQueryMetricsFactory.instance()
),
new ScanQueryEngine()
new ScanQueryEngine(),
new ScanQueryConfig()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
final class LimitedSequence<T> extends YieldingSequenceBase<T>
{
private final Sequence<T> baseSequence;
private final int limit;
private final long limit;

LimitedSequence(
Sequence<T> baseSequence,
int limit
long limit
)
{
Preconditions.checkNotNull(baseSequence);
Expand Down Expand Up @@ -106,7 +106,7 @@ public void close() throws IOException

private class LimitedYieldingAccumulator<OutType, T> extends DelegatingYieldingAccumulator<OutType, T>
{
int count;
long count;
boolean interruptYield = false;

LimitedYieldingAccumulator(YieldingAccumulator<OutType, T> accumulator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.PriorityQueue;

/**
* Used to perform an n-way merge on n ordered sequences
*/
public class MergeSequence<T> extends YieldingSequenceBase<T>
{
Expand All @@ -42,20 +43,18 @@ public MergeSequence(
this.baseSequences = (Sequence<? extends Sequence<T>>) baseSequences;
}

/*
Note: the yielder for MergeSequence returns elements from the priority queue in order of increasing priority.
This is due to the fact that PriorityQueue#remove() polls from the head of the queue which is, according to
the PriorityQueue javadoc, "the least element with respect to the specified ordering"
*/
@Override
public <OutType> Yielder<OutType> toYielder(OutType initValue, YieldingAccumulator<OutType, T> accumulator)
{
PriorityQueue<Yielder<T>> pQueue = new PriorityQueue<>(
32,
ordering.onResultOf(
new Function<Yielder<T>, T>()
{
@Override
public T apply(Yielder<T> input)
{
return input.get();
}
}
(Function<Yielder<T>, T>) input -> input.get()
)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ public interface Sequence<T>
<OutType> OutType accumulate(OutType initValue, Accumulator<OutType, T> accumulator);

/**
* Return an Yielder for accumulated sequence.
* Return a Yielder for accumulated sequence.
*
* @param initValue the initial value to pass along to start the accumulation.
* @param accumulator the accumulator which is responsible for accumulating input values.
* @param <OutType> the type of accumulated value.
*
* @return an Yielder for accumulated sequence.
* @return a Yielder for accumulated sequence.
*
* @see Yielder
*/
Expand All @@ -72,6 +72,8 @@ default <U> Sequence<U> map(Function<? super T, ? extends U> mapper)
}

/**
* This will materialize the entire sequence. Use at your own risk.
*
* Several benchmarks rely on this method to eagerly accumulate Sequences to ArrayLists. e.g.
* GroupByBenchmark.
*/
Expand All @@ -80,7 +82,7 @@ default List<T> toList()
return accumulate(new ArrayList<>(), Accumulators.list());
}

default Sequence<T> limit(int limit)
default Sequence<T> limit(long limit)
{
return new LimitedSequence<>(this, limit);
}
Expand Down
97 changes: 53 additions & 44 deletions docs/content/querying/scan-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ title: "Scan query"

# Scan query

Scan query returns raw Druid rows in streaming mode.
The Scan query returns raw Druid rows in streaming mode. The biggest difference between the Select query and the Scan
query is that the Scan query does not retain all the returned rows in memory before they are returned to the client.
The Select query _will_ retain the rows in memory, causing memory pressure if too many rows are returned.
The Scan query can return all the rows without issuing another pagination query.

In addition to straightforward usage where a Scan query is issued to the Broker, the Scan query can also be issued
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I noticed that the code that hits the historical would maybe explode if not issued a the interval with a MultipleSpecificSegmentSpec, but there is an example query immediately after mention that the historicals can be queried that doesn't have this segment spec, and is probably confusing. Querying historicals directly seems like an advanced use case, and should maybe be moved to it's own section near the end of this document to make it clear and not necessarily encouraging it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the time-ordering section, there's this line: "Also,
time ordering is not support for queries issued directly to historicals unless a list of segments is specified." (don't mind the typo, I'll fix that right now). Is that good enough?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably ok, i think it just flows strange for me when I read the section. It's because the things aren't really related but don't really feel separated.

For future work it might be nice to overhaul the scan query documentation, maybe drop mention of the legacy mode and the valueVector result format and maybe re-arrange some things. I still feel querying a historical directly is less important than describing the scan query itself, and should be pushed to the end of the docs into an 'advanced' section that describes using the scan query as a means of parallel export into another query system or whatever, but all of this can be done in a future PR

directly to Historical processes or streaming ingestion tasks. This can be useful if you want to retrieve large
amounts of data in parallel.

An example Scan query object is shown below:

```json
{
Expand All @@ -36,28 +45,29 @@ Scan query returns raw Druid rows in streaming mode.
"2013-01-01/2013-01-02"
],
"batchSize":20480,
"limit":5
"limit":3
}
```

There are several main parts to a scan query:
The following are the main parameters for Scan queries:

|property|description|required?|
|--------|-----------|---------|
|queryType|This String should always be "scan"; this is the first thing Druid looks at to figure out how to interpret the query|yes|
|dataSource|A String or Object defining the data source to query, very similar to a table in a relational database. See [DataSource](../querying/datasource.html) for more information.|yes|
|intervals|A JSON Object representing ISO-8601 Intervals. This defines the time ranges to run the query over.|yes|
|resultFormat|How result represented, list or compactedList or valueVector. Currently only `list` and `compactedList` are supported. Default is `list`|no|
|resultFormat|How the results are represented: list, compactedList or valueVector. Currently only `list` and `compactedList` are supported. Default is `list`|no|
|filter|See [Filters](../querying/filters.html)|no|
|columns|A String array of dimensions and metrics to scan. If left empty, all dimensions and metrics are returned.|no|
|batchSize|How many rows buffered before return to client. Default is `20480`|no|
|limit|How many rows to return. If not specified, all rows will be returned.|no|
|order|The ordering of returned rows based on timestamp. "ascending", "descending", and "none" (default) are supported. Currently, "ascending" and "descending" are only supported for queries where the limit is less than `druid.query.scan.maxRowsQueuedForOrdering`. Scan queries that are either legacy mode or have a limit greater than `druid.query.scan.maxRowsQueuedForOrdering` will not be time-ordered and default to a order of "none".|none|
|legacy|Return results consistent with the legacy "scan-query" contrib extension. Defaults to the value set by `druid.query.scan.legacy`, which in turn defaults to false. See [Legacy mode](#legacy-mode) for details.|no|
|context|An additional JSON Object which can be used to specify certain flags.|no|

## Example results

The format of the result when resultFormat equals to `list`:
The format of the result when resultFormat equals `list`:

```json
[{
Expand Down Expand Up @@ -123,41 +133,11 @@ The format of the result when resultFormat equals to `list`:
"delta" : 77.0,
"variation" : 77.0,
"deleted" : 0.0
}, {
"timestamp" : "2013-01-01T00:00:00.000Z",
"robot" : "0",
"namespace" : "article",
"anonymous" : "0",
"unpatrolled" : "0",
"page" : "113_U.S._73",
"language" : "en",
"newpage" : "1",
"user" : "MZMcBride",
"count" : 1.0,
"added" : 70.0,
"delta" : 70.0,
"variation" : 70.0,
"deleted" : 0.0
}, {
"timestamp" : "2013-01-01T00:00:00.000Z",
"robot" : "0",
"namespace" : "article",
"anonymous" : "0",
"unpatrolled" : "0",
"page" : "113_U.S._756",
"language" : "en",
"newpage" : "1",
"user" : "MZMcBride",
"count" : 1.0,
"added" : 68.0,
"delta" : 68.0,
"variation" : 68.0,
"deleted" : 0.0
} ]
} ]
```

The format of the result when resultFormat equals to `compactedList`:
The format of the result when resultFormat equals `compactedList`:

```json
[{
Expand All @@ -168,18 +148,39 @@ The format of the result when resultFormat equals to `compactedList`:
"events" : [
["2013-01-01T00:00:00.000Z", "1", "article", "0", "0", "11._korpus_(NOVJ)", "sl", "0", "EmausBot", 1.0, 39.0, 39.0, 39.0, 0.0],
["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "112_U.S._580", "en", "1", "MZMcBride", 1.0, 70.0, 70.0, 70.0, 0.0],
["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "113_U.S._243", "en", "1", "MZMcBride", 1.0, 77.0, 77.0, 77.0, 0.0],
["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "113_U.S._73", "en", "1", "MZMcBride", 1.0, 70.0, 70.0, 70.0, 0.0],
["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "113_U.S._756", "en", "1", "MZMcBride", 1.0, 68.0, 68.0, 68.0, 0.0]
["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "113_U.S._243", "en", "1", "MZMcBride", 1.0, 77.0, 77.0, 77.0, 0.0]
]
} ]
```

The biggest difference between select query and scan query is that, scan query doesn't retain all rows in memory before rows can be returned to client.
It will cause memory pressure if too many rows required by select query.
Scan query doesn't have this issue.
Scan query can return all rows without issuing another pagination query, which is extremely useful when query against Historical or realtime process directly.

## Time Ordering

The Scan query currently supports ordering based on timestamp for non-legacy queries. Note that using time ordering
will yield results that do not indicate which segment rows are from (`segmentId` will show up as `null`). Furthermore,
time ordering is only supported where the result set limit is less than `druid.query.scan.maxRowsQueuedForOrdering`
rows **or** all segments scanned have fewer than `druid.query.scan.maxSegmentPartitionsOrderedInMemory` partitions. Also,
time ordering is not supported for queries issued directly to historicals unless a list of segments is specified. The
reasoning behind these limitations is that the implementation of time ordering uses two strategies that can consume too
much heap memory if left unbounded. These strategies (listed below) are chosen on a per-Historical basis depending on
query result set limit and the number of segments being scanned.

1. Priority Queue: Each segment on a Historical is opened sequentially. Every row is added to a bounded priority
queue which is ordered by timestamp. For every row above the result set limit, the row with the earliest (if descending)
or latest (if ascending) timestamp will be dequeued. After every row has been processed, the sorted contents of the
priority queue are streamed back to the Broker(s) in batches. Attempting to load too many rows into memory runs the
risk of Historical nodes running out of memory. The `druid.query.scan.maxRowsQueuedForOrdering` property protects
from this by limiting the number of rows in the query result set when time ordering is used.

2. N-Way Merge: For each segment, each partition is opened in parallel. Since each partition's rows are already
time-ordered, an n-way merge can be performed on the results from each partition. This approach doesn't persist the entire
result set in memory (like the Priority Queue) as it streams back batches as they are returned from the merge function.
However, attempting to query too many partition could also result in high memory usage due to the need to open
decompression and decoding buffers for each. The `druid.query.scan.maxSegmentPartitionsOrderedInMemory` limit protects
from this by capping the number of partitions opened at any times when time ordering is used.

Both `druid.query.scan.maxRowsQueuedForOrdering` and `druid.query.scan.maxSegmentPartitionsOrderedInMemory` are
configurable and can be tuned based on hardware specs and number of dimensions being queried.

## Legacy mode

The Scan query supports a legacy mode designed for protocol compatibility with the former scan-query contrib extension.
Expand All @@ -194,3 +195,11 @@ Legacy mode can be triggered either by passing `"legacy" : true` in your query J
`druid.query.scan.legacy = true` on your Druid processes. If you were previously using the scan-query contrib extension,
the best way to migrate is to activate legacy mode during a rolling upgrade, then switch it off after the upgrade
is complete.

## Configuration Properties

|property|description|values|default|
|--------|-----------|------|-------|
|druid.query.scan.maxRowsQueuedForOrdering|The maximum number of rows returned when time ordering is used|An integer in [0, 2147483647]|100000|
|druid.query.scan.maxSegmentPartitionsOrderedInMemory|The maximum number of segments scanned per historical when time ordering is used|An integer in [0, 2147483647]|50|
|druid.query.scan.legacy|Whether legacy mode should be turned on for Scan queries|true or false|false|
Original file line number Diff line number Diff line change
Expand Up @@ -2586,7 +2586,8 @@ public void registerQuery(Query query, ListenableFuture future)
new ScanQueryConfig(),
new DefaultGenericQueryMetricsFactory(TestHelper.makeJsonMapper())
),
new ScanQueryEngine()
new ScanQueryEngine(),
new ScanQueryConfig()
)
)
.build()
Expand Down
16 changes: 13 additions & 3 deletions processing/src/main/java/org/apache/druid/query/Druids.java
Original file line number Diff line number Diff line change
Expand Up @@ -918,12 +918,13 @@ public static class ScanQueryBuilder
private QuerySegmentSpec querySegmentSpec;
private VirtualColumns virtualColumns;
private Map<String, Object> context;
private String resultFormat;
private ScanQuery.ResultFormat resultFormat;
private int batchSize;
private long limit;
private DimFilter dimFilter;
private List<String> columns;
private Boolean legacy;
private ScanQuery.Order order;

public ScanQueryBuilder()
{
Expand All @@ -937,6 +938,7 @@ public ScanQueryBuilder()
dimFilter = null;
columns = new ArrayList<>();
legacy = null;
order = null;
}

public ScanQuery build()
Expand All @@ -948,6 +950,7 @@ public ScanQuery build()
resultFormat,
batchSize,
limit,
order,
dimFilter,
columns,
legacy,
Expand All @@ -967,7 +970,8 @@ public static ScanQueryBuilder copy(ScanQuery query)
.filters(query.getFilter())
.columns(query.getColumns())
.legacy(query.isLegacy())
.context(query.getContext());
.context(query.getContext())
.order(query.getOrder());
}

public ScanQueryBuilder dataSource(String ds)
Expand Down Expand Up @@ -1005,7 +1009,7 @@ public ScanQueryBuilder context(Map<String, Object> c)
return this;
}

public ScanQueryBuilder resultFormat(String r)
public ScanQueryBuilder resultFormat(ScanQuery.ResultFormat r)
{
resultFormat = r;
return this;
Expand Down Expand Up @@ -1046,6 +1050,12 @@ public ScanQueryBuilder legacy(Boolean legacy)
this.legacy = legacy;
return this;
}

public ScanQueryBuilder order(ScanQuery.Order order)
{
this.order = order;
return this;
}
}

public static ScanQueryBuilder newScanQueryBuilder()
Expand Down
Loading