cetra3 commented on code in PR #26630:
URL: https://github.com/apache/datafusion/pull/26630#discussion_r4384287330


##########
datafusion/common/src/dfschema.rs:
##########
@@ -1159,6 +1210,116 @@ impl Hash for DFSchema {
     }
 }
 
+// `name_index` is derived state, so it is left out of equality and `Debug`.
+impl PartialEq for DFSchema {
+    fn eq(&self, other: &Self) -> bool {
+        self.inner == other.inner
+            && self.field_qualifiers == other.field_qualifiers
+            && self.functional_dependencies == other.functional_dependencies
+    }
+}
+
+impl Eq for DFSchema {}
+
+impl std::fmt::Debug for DFSchema {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("DFSchema")
+            .field("inner", &self.inner)
+            .field("field_qualifiers", &self.field_qualifiers)
+            .field("functional_dependencies", &self.functional_dependencies)
+            .finish()
+    }
+}
+
+/// Schemas with up to this many fields resolve names by comparing against 
every
+/// field; wider ones use a lazily built [`NameIndex`]. Below it, the scan is
+/// cheaper than building the index (the same trade-off as
+/// `LINEAR_FIELD_SCAN_MAX` in `datafusion-datasource-parquet`).
+const LINEAR_NAME_SCAN_MAX: usize = 8;

Review Comment:
   You're right that both regressions are real; the "within noise" line came 
from a bad local run. I've done a sweep with `sql_planner`. Each threshold was 
run twice, interleaved with three runs of `main` that agreed within ±0.3%:
   
   | Benchmark | `main` | 8 (this PR) | 64 | 256 |
   |---|---|---|---|---|
   | `logical_union_8_branches` | 339.1 µs | +2.1% / +1.8% | +2.2% / +2.1% | 
−0.2% / −0.3% |
   | `logical_correlated_subquery_in` | 109.9 µs | +1.7% / +1.4% | +1.4% / 
+1.2% | +0.2% / −0.3% |
   | `with_param_values_many_columns` | 228.0 µs | −36.8% / −36.8% | −35.4% / 
−35.7% | −16.4% / −14.8% |
   | `logical_trivial_join_high_numbered_columns` | 113.2 µs | −6.7% / −6.3% | 
−6.9% / −6.5% | −6.7% / −6.6% |
   | `physical_many_self_joins` | 4.36 ms | −5.6% / −5.9% | −6.1% / −5.8% | 
−5.8% / −5.0% |
   | `*_select_all_from_1000` (3 benchmarks) | 4.2–10.6 ms | −67% | −67% | −67% 
|
   | `optimizer_tpcds_all` | 155.5 ms | −2.8% / −2.7% | −2.7% / −2.3% | −1.8% / 
−2.4% |
   | Other 6 benchmarks | | within ±2% | within ±2% | within ±2% |
   
   64 behaves the same as 8, since no schema in these benchmarks has between 9 
and 64 columns. 256 removes the cost on `union_8` and `correlated_in`, but 
`with_param_values_many_columns` plans `SELECT MAX(a0), …, MAX(a199)` over the 
same 200-column `t1`, and it loses about 20 points.
   
   So on the same 200-column table, the index costs about 7 µs when 2 columns 
are projected and saves about 46 µs when 200 are. Width alone can't tell those 
apart. A local microbenchmark agrees: building the index costs about 4 ns per 
field, and it pays for itself after 4–8 lookups at every width from 32 to 1000. 
I've kept 8, so the remaining cost is bounded by one index build per wide 
schema that gets looked up.
   
   `SELECT id` over the 10,240-column file takes 23 ms on both `main` and this 
PR.
   



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