use of org.apache.druid.segment.column.NumericColumn in project druid by druid-io.
the class QueryableIndexCursorSequenceBuilder method buildVectorized.
public VectorCursor buildVectorized(final int vectorSize) {
// Sanity check - matches QueryableIndexStorageAdapter.canVectorize
Preconditions.checkState(!descending, "!descending");
final Map<String, BaseColumn> columnCache = new HashMap<>();
final Closer closer = Closer.create();
NumericColumn timestamps = null;
final int startOffset;
final int endOffset;
if (interval.getStartMillis() > minDataTimestamp) {
timestamps = (NumericColumn) index.getColumnHolder(ColumnHolder.TIME_COLUMN_NAME).getColumn();
closer.register(timestamps);
startOffset = timeSearch(timestamps, interval.getStartMillis(), 0, index.getNumRows());
} else {
startOffset = 0;
}
if (interval.getEndMillis() <= maxDataTimestamp) {
if (timestamps == null) {
timestamps = (NumericColumn) index.getColumnHolder(ColumnHolder.TIME_COLUMN_NAME).getColumn();
closer.register(timestamps);
}
endOffset = timeSearch(timestamps, interval.getEndMillis(), startOffset, index.getNumRows());
} else {
endOffset = index.getNumRows();
}
final VectorOffset baseOffset = filterBitmap == null ? new NoFilterVectorOffset(vectorSize, startOffset, endOffset) : new BitmapVectorOffset(vectorSize, filterBitmap, startOffset, endOffset);
// baseColumnSelectorFactory using baseOffset is the column selector for filtering.
final VectorColumnSelectorFactory baseColumnSelectorFactory = makeVectorColumnSelectorFactoryForOffset(columnCache, baseOffset, closer);
if (postFilter == null) {
return new QueryableIndexVectorCursor(baseColumnSelectorFactory, baseOffset, vectorSize, closer);
} else {
final VectorOffset filteredOffset = FilteredVectorOffset.create(baseOffset, baseColumnSelectorFactory, postFilter);
// Now create the cursor and column selector that will be returned to the caller.
//
// There is an inefficiency with how we do things here: this cursor (the one that will be provided to the
// caller) does share a columnCache with "baseColumnSelectorFactory", but it *doesn't* share vector data. This
// means that if the caller wants to read from a column that is also used for filtering, the underlying column
// object will get hit twice for some of the values (anything that matched the filter). This is probably most
// noticeable if it causes thrashing of decompression buffers due to out-of-order reads. I haven't observed
// this directly but it seems possible in principle.
// baseColumnSelectorFactory using baseOffset is the column selector for filtering.
final VectorColumnSelectorFactory filteredColumnSelectorFactory = makeVectorColumnSelectorFactoryForOffset(columnCache, filteredOffset, closer);
return new QueryableIndexVectorCursor(filteredColumnSelectorFactory, filteredOffset, vectorSize, closer);
}
}
use of org.apache.druid.segment.column.NumericColumn in project druid by druid-io.
the class QueryableIndexCursorSequenceBuilderTest method testTimeSearch.
@Test
public void testTimeSearch() {
final int[] values = new int[] { 0, 1, 1, 1, 1, 1, 1, 1, 5, 7, 10 };
final NumericColumn column = new NumericColumn() {
@Override
public int length() {
return values.length;
}
@Override
public long getLongSingleValueRow(int rowNum) {
return values[rowNum];
}
@Override
public void close() {
throw new UnsupportedOperationException();
}
@Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) {
throw new UnsupportedOperationException();
}
@Override
public ColumnValueSelector<?> makeColumnValueSelector(ReadableOffset offset) {
throw new UnsupportedOperationException();
}
};
Assert.assertEquals(0, QueryableIndexCursorSequenceBuilder.timeSearch(column, 0, 0, values.length));
Assert.assertEquals(2, QueryableIndexCursorSequenceBuilder.timeSearch(column, 0, 2, values.length));
Assert.assertEquals(0, QueryableIndexCursorSequenceBuilder.timeSearch(column, 0, 0, values.length / 2));
Assert.assertEquals(1, QueryableIndexCursorSequenceBuilder.timeSearch(column, 1, 0, values.length));
Assert.assertEquals(2, QueryableIndexCursorSequenceBuilder.timeSearch(column, 1, 2, values.length));
Assert.assertEquals(1, QueryableIndexCursorSequenceBuilder.timeSearch(column, 1, 0, values.length / 2));
Assert.assertEquals(1, QueryableIndexCursorSequenceBuilder.timeSearch(column, 1, 1, 8));
Assert.assertEquals(8, QueryableIndexCursorSequenceBuilder.timeSearch(column, 2, 0, values.length));
Assert.assertEquals(10, QueryableIndexCursorSequenceBuilder.timeSearch(column, 10, 0, values.length));
Assert.assertEquals(11, QueryableIndexCursorSequenceBuilder.timeSearch(column, 15, 0, values.length));
}
use of org.apache.druid.segment.column.NumericColumn in project druid by druid-io.
the class UseIndexesStrategy method makeTimeFilteredBitmap.
static ImmutableBitmap makeTimeFilteredBitmap(final QueryableIndex index, final Segment segment, final Filter filter, final Interval interval) {
final BitmapFactory bitmapFactory = index.getBitmapFactoryForDimensions();
final ImmutableBitmap baseFilter;
if (filter == null) {
baseFilter = null;
} else {
final BitmapIndexSelector selector = new ColumnSelectorBitmapIndexSelector(index.getBitmapFactoryForDimensions(), VirtualColumns.EMPTY, index);
Preconditions.checkArgument(filter.supportsBitmapIndex(selector), "filter[%s] should support bitmap", filter);
baseFilter = filter.getBitmapIndex(selector);
}
final ImmutableBitmap timeFilteredBitmap;
if (!interval.contains(segment.getDataInterval())) {
final MutableBitmap timeBitmap = bitmapFactory.makeEmptyMutableBitmap();
final ColumnHolder timeColumnHolder = index.getColumnHolder(ColumnHolder.TIME_COLUMN_NAME);
try (final NumericColumn timeValues = (NumericColumn) timeColumnHolder.getColumn()) {
int startIndex = Math.max(0, getStartIndexOfTime(timeValues, interval.getStartMillis(), true));
int endIndex = Math.min(timeValues.length() - 1, getStartIndexOfTime(timeValues, interval.getEndMillis(), false));
for (int i = startIndex; i <= endIndex; i++) {
timeBitmap.add(i);
}
final ImmutableBitmap finalTimeBitmap = bitmapFactory.makeImmutableBitmap(timeBitmap);
timeFilteredBitmap = (baseFilter == null) ? finalTimeBitmap : finalTimeBitmap.intersection(baseFilter);
}
} else {
timeFilteredBitmap = baseFilter;
}
return timeFilteredBitmap;
}
use of org.apache.druid.segment.column.NumericColumn in project druid by druid-io.
the class QueryableIndexCursorSequenceBuilder method build.
public Sequence<Cursor> build(final Granularity gran) {
final Offset baseOffset;
if (filterBitmap == null) {
baseOffset = descending ? new SimpleDescendingOffset(index.getNumRows()) : new SimpleAscendingOffset(index.getNumRows());
} else {
baseOffset = BitmapOffset.of(filterBitmap, descending, index.getNumRows());
}
// Column caches shared amongst all cursors in this sequence.
final Map<String, BaseColumn> columnCache = new HashMap<>();
final NumericColumn timestamps = (NumericColumn) index.getColumnHolder(ColumnHolder.TIME_COLUMN_NAME).getColumn();
final Closer closer = Closer.create();
closer.register(timestamps);
Iterable<Interval> iterable = gran.getIterable(interval);
if (descending) {
iterable = Lists.reverse(ImmutableList.copyOf(iterable));
}
return Sequences.withBaggage(Sequences.map(Sequences.simple(iterable), new Function<Interval, Cursor>() {
@Override
public Cursor apply(final Interval inputInterval) {
final long timeStart = Math.max(interval.getStartMillis(), inputInterval.getStartMillis());
final long timeEnd = Math.min(interval.getEndMillis(), gran.increment(inputInterval.getStartMillis()));
if (descending) {
for (; baseOffset.withinBounds(); baseOffset.increment()) {
if (timestamps.getLongSingleValueRow(baseOffset.getOffset()) < timeEnd) {
break;
}
}
} else {
for (; baseOffset.withinBounds(); baseOffset.increment()) {
if (timestamps.getLongSingleValueRow(baseOffset.getOffset()) >= timeStart) {
break;
}
}
}
final Offset offset = descending ? new DescendingTimestampCheckingOffset(baseOffset, timestamps, timeStart, minDataTimestamp >= timeStart) : new AscendingTimestampCheckingOffset(baseOffset, timestamps, timeEnd, maxDataTimestamp < timeEnd);
final Offset baseCursorOffset = offset.clone();
final ColumnSelectorFactory columnSelectorFactory = new QueryableIndexColumnSelectorFactory(index, virtualColumns, descending, closer, baseCursorOffset.getBaseReadableOffset(), columnCache);
final DateTime myBucket = gran.toDateTime(inputInterval.getStartMillis());
if (postFilter == null) {
return new QueryableIndexCursor(baseCursorOffset, columnSelectorFactory, myBucket);
} else {
FilteredOffset filteredOffset = new FilteredOffset(baseCursorOffset, columnSelectorFactory, descending, postFilter, bitmapIndexSelector);
return new QueryableIndexCursor(filteredOffset, columnSelectorFactory, myBucket);
}
}
}), closer);
}
use of org.apache.druid.segment.column.NumericColumn in project druid by druid-io.
the class QueryableIndexStorageAdapter method populateMinMaxTime.
private void populateMinMaxTime() {
// Compute and cache minTime, maxTime.
final ColumnHolder columnHolder = index.getColumnHolder(ColumnHolder.TIME_COLUMN_NAME);
try (final NumericColumn column = (NumericColumn) columnHolder.getColumn()) {
this.minTime = DateTimes.utc(column.getLongSingleValueRow(0));
this.maxTime = DateTimes.utc(column.getLongSingleValueRow(column.length() - 1));
}
}
Aggregations