Aggarwal-Raghav commented on code in PR #6741:
URL: https://github.com/apache/hive/pull/6741#discussion_r3890339740
##########
ql/src/java/org/apache/hadoop/hive/ql/io/parquet/ParquetRecordReaderBase.java:
##########
@@ -181,6 +186,95 @@ protected ParquetInputSplit getSplit(
return split;
}
+ /**
+ * Prunes the row groups of this split with the pushed down predicate.
+ *
+ * <p>Statistics come from the footer, which is already in memory. Bloom
filters live in the data file and
+ * need an open reader, so one is opened only after statistics have had
their say and only while a
+ * surviving row group still carries a bloom filter.
+ *
+ * <p>The reader is built from a copy of the job conf with the pushed down
predicate removed. Parquet reads
+ * that predicate from the conf and filters row groups inside the
constructor; leaving it in place would
+ * read every bloom filter twice and every dictionary page once, only to
discard the result.
+ */
+ private List<BlockMetaData> filterRowGroups(FilterCompat.Filter filter,
List<BlockMetaData> splitGroup,
+ FileMetaData fileMetaData) throws IOException {
+ List<BlockMetaData> statsFiltered =
+ RowGroupFilter.filterRowGroups(filter, splitGroup,
fileMetaData.getSchema());
+ Set<ColumnPath> prunableColumns = bloomFilterPrunableColumns(filter);
+ if (statsFiltered.isEmpty() ||
!jobConf.getBoolean(ParquetInputFormat.BLOOM_FILTERING_ENABLED, true) ||
+ prunableColumns.isEmpty() || !hasBloomFilters(statsFiltered,
prunableColumns)) {
+ return statsFiltered;
+ }
+
+ JobConf bloomFilterConf = new JobConf(jobConf);
+ bloomFilterConf.unset(ParquetInputFormat.FILTER_PREDICATE);
+ // filePath, not the split path: LLAP may rewrite it to a file id path,
and the bloom filter offsets
+ // being used here come from the footer that was read from it.
+ try (ParquetFileReader bloomFilterReader = new
ParquetFileReader(bloomFilterConf, fileMetaData, filePath,
+ statsFiltered, fileMetaData.getSchema().getColumns())) {
+ return RowGroupFilter.filterRowGroups(
+ Collections.singletonList(RowGroupFilter.FilterLevel.BLOOMFILTER),
filter, statsFiltered,
+ bloomFilterReader);
+ }
+ }
+
+ /**
+ * The columns this predicate could prune a row group on with a bloom
filter. A bloom filter only proves
+ * that a value is absent, so it serves equality and set membership and
nothing else, and only for the
+ * columns those terms name. An empty result means opening the data file
could not pay off. Parquet
+ * reaches the same conclusion in BloomFilterImpl, but only once the reader
is already open.
+ */
+ private static Set<ColumnPath>
bloomFilterPrunableColumns(FilterCompat.Filter filter) {
+ return filter instanceof FilterCompat.FilterPredicateCompat ?
+ bloomFilterPrunableColumns(((FilterCompat.FilterPredicateCompat)
filter).getFilterPredicate()) :
+ Collections.emptySet();
+ }
+
+ private static Set<ColumnPath> bloomFilterPrunableColumns(FilterPredicate
predicate) {
+ if (predicate instanceof Operators.Eq) {
+ Operators.Eq<?> eq = (Operators.Eq<?>) predicate;
+ // eq(col, null) asks for nulls, which a bloom filter says nothing about
+ return eq.getValue() == null ? Collections.emptySet() :
+ Collections.singleton(eq.getColumn().getColumnPath());
+ }
+ if (predicate instanceof Operators.In) {
+ // Hive builds IN as a chain of ORed equalities rather than this node,
but honor it if that changes
+ return Collections.singleton(((Operators.In<?>)
predicate).getColumn().getColumnPath());
+ }
+ if (predicate instanceof Operators.And) {
+ Operators.And and = (Operators.And) predicate;
+ // dropping either side of a conjunction drops the row group
+ return union(bloomFilterPrunableColumns(and.getLeft()),
bloomFilterPrunableColumns(and.getRight()));
+ }
+ if (predicate instanceof Operators.Or) {
Review Comment:
nit for readablity 😬: `Set.Of` can be use instead of Collections
then the `Collections.emptySet() :
Collections.singleton(eq.getColumn().getColumnPath());`
be `Set.of() : Set.of(eq.getColumn().getColumnPath());`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]