mirror of
https://github.com/apache/impala.git
synced 2025-12-21 19:08:12 -05:00
ORC files have optional bloom filter indexes for each column. Since ORC-1.7.0, the C++ reader supports pushing down predicates to skip unreleated RowGroups. The pushed down predicates will be evaludated on file indexes (i.e. statistics and bloom filter indexes). Note that only EQUALS and IN-list predicates can leverage bloom filter indexes. Currently Impala has two kinds of runtime filters: bloom filter and min-max filter. Unfortunately they can't be converted into EQUALS or IN-list predicates. So they can't leverage the file level bloom filter indexes. This patch adds runtime IN-list filters for this purpose. Currently they are generated for the build side of a broadcast join. They will only be applied on ORC tables and be pushed down to the ORC reader(i.e. ORC lib). To avoid exploding the IN-list, if # of distinct values of the build side exceeds a threshold (default to 1024), we set the filter to ALWAYS_TRUE and clear its entry. The threshold can be configured by a new query option, RUNTIME_IN_LIST_FILTER_ENTRY_LIMIT. Evaluating runtime IN-list filters is much slower than evaluating runtime bloom filters due to the current simple implementation (i.e. std::unorder_set) and the lack of codegen. So we disable it at row level. For visibility, this patch addes two counters in the HdfsScanNode: - NumPushedDownPredicates - NumPushedDownRuntimeFilters They reflect the predicates and runtime filters that are pushed down to the ORC reader. Currently, runtime IN-list filters are disabled by default. This patch extends the query option, ENABLED_RUNTIME_FILTER_TYPES, to support a comma separated list of filter types. It defaults to be "BLOOM,MIN_MAX". Add "IN_LIST" in it to enable runtime IN-list filters. Ran perf tests on a 3 instances cluster on my desktop using TPC-DS with scale factor 20. It shows significant improvements in some queries: +-----------+-------------+--------------------+--------+-------------+------------+------------+----------------+-------+----------------+---------+--------+ | Workload | Query | File Format | Avg(s) | Base Avg(s) | Delta(Avg) | StdDev(%) | Base StdDev(%) | Iters | Median Diff(%) | MW Zval | Tval | +-----------+-------------+--------------------+--------+-------------+------------+------------+----------------+-------+----------------+---------+--------+ | TPCDS(20) | TPCDS-Q67A | orc / snap / block | 35.07 | 44.01 | I -20.32% | 0.38% | 1.38% | 10 | I -25.69% | -3.58 | -45.33 | | TPCDS(20) | TPCDS-Q37 | orc / snap / block | 1.08 | 1.45 | I -25.23% | 7.14% | 3.09% | 10 | I -34.09% | -3.58 | -12.94 | | TPCDS(20) | TPCDS-Q70A | orc / snap / block | 6.30 | 8.60 | I -26.81% | 5.24% | 4.21% | 10 | I -36.67% | -3.58 | -14.88 | | TPCDS(20) | TPCDS-Q16 | orc / snap / block | 1.33 | 1.85 | I -28.28% | 4.98% | 5.92% | 10 | I -39.38% | -3.58 | -12.93 | | TPCDS(20) | TPCDS-Q18A | orc / snap / block | 5.70 | 8.06 | I -29.25% | 3.00% | 4.12% | 10 | I -40.30% | -3.58 | -19.95 | | TPCDS(20) | TPCDS-Q22A | orc / snap / block | 2.01 | 2.97 | I -32.21% | 6.12% | 5.94% | 10 | I -47.68% | -3.58 | -14.05 | | TPCDS(20) | TPCDS-Q77A | orc / snap / block | 8.49 | 12.44 | I -31.75% | 6.44% | 3.96% | 10 | I -49.71% | -3.58 | -16.97 | | TPCDS(20) | TPCDS-Q75 | orc / snap / block | 7.76 | 12.27 | I -36.76% | 5.01% | 3.87% | 10 | I -59.56% | -3.58 | -23.26 | | TPCDS(20) | TPCDS-Q21 | orc / snap / block | 0.71 | 1.27 | I -44.26% | 4.56% | 4.24% | 10 | I -77.31% | -3.58 | -28.31 | | TPCDS(20) | TPCDS-Q80A | orc / snap / block | 9.24 | 20.42 | I -54.77% | 4.03% | 3.82% | 10 | I -123.12% | -3.58 | -40.90 | | TPCDS(20) | TPCDS-Q39-1 | orc / snap / block | 1.07 | 2.26 | I -52.74% | * 23.83% * | 2.60% | 10 | I -149.68% | -3.58 | -14.43 | | TPCDS(20) | TPCDS-Q39-2 | orc / snap / block | 1.00 | 2.33 | I -56.95% | * 19.53% * | 2.07% | 10 | I -151.89% | -3.58 | -20.81 | +-----------+-------------+--------------------+--------+-------------+------------+------------+----------------+-------+----------------+---------+--------+ "Base Avg" is the avg of the original time. "Avg" is the current time. However, we also see some regressions due to the suboptimal implementation. The follow-up JIRAs will focus on improvements: - IMPALA-11140: Codegen InListFilter::Insert() and InListFilter::Find() - IMPALA-11141: Use exact data types in IN-list filters instead of casting data to a set of int64_t or a set of string. - IMPALA-11142: Consider IN-list filters in partitioned joins. Tests: - Test IN-list filter on string, date and all integer types - Test IN-list filter with NULL - Test IN-list filter on complex exprs targets Change-Id: I25080628233799aa0b6be18d5a832f1385414501 Reviewed-on: http://gerrit.cloudera.org:8080/18141 Reviewed-by: Qifan Chen <qchen@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
181 lines
5.8 KiB
Protocol Buffer
181 lines
5.8 KiB
Protocol Buffer
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
//
|
|
|
|
syntax="proto2";
|
|
|
|
package impala;
|
|
|
|
import "common.proto";
|
|
import "row_batch.proto";
|
|
|
|
import "kudu/rpc/rpc_header.proto";
|
|
|
|
// All fields are required in V1.
|
|
message TransmitDataRequestPB {
|
|
// The fragment instance id of the receiver.
|
|
optional UniqueIdPB dest_fragment_instance_id = 1;
|
|
|
|
// Sender instance id, unique within a fragment.
|
|
optional int32 sender_id = 2;
|
|
|
|
// PlanNodeId of the exchange node which owns the receiver.
|
|
optional int32 dest_node_id = 3;
|
|
|
|
// The header which contains the meta-data of the row batch.
|
|
optional RowBatchHeaderPB row_batch_header = 4;
|
|
|
|
// The sidecar index of tuple offsets' buffer which is an array of int32 containing the
|
|
// offsets of tuples into the buffer pointed to by tuple data's sidecar below. There are
|
|
// num_rows * num_tuples_per_row offsets in total. An offset of -1 records a NULL.
|
|
optional int32 tuple_offsets_sidecar_idx = 5;
|
|
|
|
// The sidecar index of the tuple's data which is a (compressed) row batch.
|
|
// The details of the row batch (e.g. # of rows) is in 'row_batch_header' above.
|
|
optional int32 tuple_data_sidecar_idx = 6;
|
|
}
|
|
|
|
// All fields are required in V1.
|
|
message TransmitDataResponsePB {
|
|
// Status::OK() on success; Error status on failure.
|
|
optional StatusPB status = 1;
|
|
|
|
// Latency for response in the receiving daemon in nanoseconds.
|
|
optional int64 receiver_latency_ns = 2;
|
|
}
|
|
|
|
// All fields are required in V1.
|
|
message EndDataStreamRequestPB {
|
|
// The fragment instance id of the receiver.
|
|
optional UniqueIdPB dest_fragment_instance_id = 1;
|
|
|
|
// Sender instance id, unique within a fragment.
|
|
optional int32 sender_id = 2;
|
|
|
|
// PlanNodeId of the exchange node which owns the receiver.
|
|
optional int32 dest_node_id = 3;
|
|
}
|
|
|
|
// All fields are required in V1.
|
|
message EndDataStreamResponsePB {
|
|
optional StatusPB status = 1;
|
|
|
|
// Latency for response in the receiving daemon in nanoseconds.
|
|
optional int64 receiver_latency_ns = 2;
|
|
}
|
|
|
|
message BloomFilterPB {
|
|
// Log_2 of the bufferpool space required for this filter.
|
|
// See BloomFilter::BloomFilter() for details.
|
|
optional int32 log_bufferpool_space = 1;
|
|
|
|
// If always_true or always_false is true, 'directory' and 'log_bufferpool_space' are
|
|
// not meaningful.
|
|
optional bool always_true = 2;
|
|
optional bool always_false = 3;
|
|
|
|
// The sidecar index associated with the directory of a Bloom filter.
|
|
// A directory is a list of buckets representing the Bloom Filter contents,
|
|
// laid out contiguously in one string for efficiency of (de)serialisation.
|
|
// See BloomFilter::Bucket and BloomFilter::directory_.
|
|
optional int32 directory_sidecar_idx = 4;
|
|
}
|
|
|
|
message MinMaxFilterPB {
|
|
// If true, filter allows all elements to pass and 'min'/'max' will not be set.
|
|
optional bool always_true = 1;
|
|
|
|
// If true, filter doesn't allow any elements to pass and 'min'/'max' will not be set.
|
|
optional bool always_false = 2;
|
|
|
|
optional ColumnValuePB min = 3;
|
|
optional ColumnValuePB max = 4;
|
|
}
|
|
|
|
message InListFilterPB {
|
|
optional bool always_true = 1;
|
|
optional bool contains_null = 2;
|
|
repeated ColumnValuePB value = 3;
|
|
}
|
|
|
|
message UpdateFilterParamsPB {
|
|
// Filter ID, unique within a query.
|
|
optional int32 filter_id = 1;
|
|
|
|
// Query that this filter is for.
|
|
optional UniqueIdPB query_id = 2;
|
|
|
|
optional BloomFilterPB bloom_filter = 3;
|
|
|
|
optional MinMaxFilterPB min_max_filter = 4;
|
|
|
|
optional InListFilterPB in_list_filter = 5;
|
|
}
|
|
|
|
message UpdateFilterResultPB {
|
|
optional StatusPB status = 1;
|
|
|
|
// Latency for response in the receiving daemon in nanoseconds.
|
|
optional int64 receiver_latency_ns = 2;
|
|
}
|
|
|
|
message PublishFilterParamsPB {
|
|
// Filter ID, unique within a query.
|
|
optional int32 filter_id = 1;
|
|
|
|
// Query that this filter is for.
|
|
optional UniqueIdPB dst_query_id = 2;
|
|
|
|
// Actual bloom_filter payload
|
|
optional BloomFilterPB bloom_filter = 3;
|
|
|
|
// Actual min_max_filter payload
|
|
optional MinMaxFilterPB min_max_filter = 4;
|
|
|
|
// Actual in_list_filter payload
|
|
optional InListFilterPB in_list_filter = 5;
|
|
}
|
|
|
|
message PublishFilterResultPB {
|
|
optional StatusPB status = 1;
|
|
|
|
// Latency for response in the receiving daemon in nanoseconds.
|
|
optional int64 receiver_latency_ns = 2;
|
|
}
|
|
|
|
// Handles data transmission between fragment instances.
|
|
service DataStreamService {
|
|
// Override the default authorization method.
|
|
option (kudu.rpc.default_authz_method) = "Authorize";
|
|
|
|
// Called by sender to transmit a single row batch. Returns error indication
|
|
// if params.fragmentId or params.destNodeId are unknown or if data couldn't
|
|
// be read.
|
|
rpc TransmitData(TransmitDataRequestPB) returns (TransmitDataResponsePB);
|
|
|
|
// Called by a sender to close the channel between fragment instances.
|
|
rpc EndDataStream(EndDataStreamRequestPB) returns (EndDataStreamResponsePB);
|
|
|
|
// Called by fragment instances that produce local runtime filters to deliver them to
|
|
// the coordinator for aggregation and broadcast.
|
|
rpc UpdateFilter(UpdateFilterParamsPB) returns (UpdateFilterResultPB);
|
|
|
|
// Called by the coordinator to deliver global runtime filters to fragments for
|
|
// application at plan nodes.
|
|
rpc PublishFilter(PublishFilterParamsPB) returns (PublishFilterResultPB);
|
|
}
|