HappenLee commented on code in PR #66455:
URL: https://github.com/apache/doris/pull/66455#discussion_r3810960910


##########
be/src/exprs/expr_zonemap_filter.cpp:
##########
@@ -461,43 +445,57 @@ ZoneMapFilterResult eval_in_zonemap(const 
ZoneMapEvalContext& ctx, const VExprSP
         return unsupported_zonemap_filter(ctx);
     }
 
+    // A non-empty set without ordered bounds contains only NaN values. Once 
the reader proves the
+    // data has no hidden NaNs, such an IN cannot match while NOT IN remains 
conservative.
+    if (values.min_value.is_null() || values.max_value.is_null()) {
+        DORIS_CHECK(values.contains_nan);
+        DORIS_CHECK(values.min_value.is_null());
+        DORIS_CHECK(values.max_value.is_null());
+        return is_not_in ? ZoneMapFilterResult::kMayMatch : 
ZoneMapFilterResult::kNoMatch;
+    }
+
+    // The caller has precomputed the IN set's owning non-NaN min/max. They 
must match the expression
+    // slot type before being compared with storage zone-map statistics.
+    DORIS_CHECK(
+            field_types_compatible(values.min_value.get_type(), 
data_type->get_primitive_type()));
+    DORIS_CHECK(
+            field_types_compatible(values.max_value.get_type(), 
data_type->get_primitive_type()));
+
     if (is_not_in) {
         // NOT IN can only prune when the whole zone contains exactly one 
non-null value and that
         // value is excluded by the set. Wider ranges may contain values that 
are not filtered.
         if (zone_map.min_value == zone_map.max_value) {
-            const bool only_value_is_filtered = std::ranges::any_of(
-                    values, [&](const Field& value) { return value == 
zone_map.min_value; });
+            const bool only_value_is_filtered = set.find(zone_map.min_value);
             return only_value_is_filtered ? ZoneMapFilterResult::kNoMatch
                                           : ZoneMapFilterResult::kMayMatch;
         }
         return ZoneMapFilterResult::kMayMatch;
     }
 
-    // First use the materialized IN-set min/max to rule out disjoint zone-map 
ranges.
-    if (zone_map.max_value < min_value || zone_map.min_value > max_value) {
+    // First use the IN-set min/max to rule out disjoint zone-map ranges.
+    if (zone_map.max_value < values.min_value || zone_map.min_value > 
values.max_value) {
         return ZoneMapFilterResult::kNoMatch;
     }
 
-    // For large IN sets, avoid checking every point on the scan hot path. The 
range overlap above
-    // is only a coarse may-match signal.
-    if (values.size() > kInZoneMapPointCheckThreshold) {
+    // For large IN sets and dense-domain containers, avoid exact checks on 
the scan hot path. A
+    // BitSet iterator may inspect its entire value domain even when the set 
itself is small.
+    if (!set.supports_fast_range_lookup() ||

Review Comment:
   BitSet should can dispose zonemap in fast path



-- 
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]

Reply via email to