voonhous opened a new issue, #20537:
URL: https://github.com/apache/hudi/issues/20537

   ### Describe the problem
   
   A column stats expression index prunes files only for `=` (and for `IN` when 
the source column needs no cast). Range predicates on the indexed expression 
(`>`, `>=`, `<`, `<=`, `BETWEEN`) never use it, so every file is scanned.
   
   `ExpressionIndexSupport.extractQueryAndLiterals` picks the filter to 
evaluate through `RecordLevelIndexSupport.filterQueryWithRecordKey` 
(`RecordLevelIndexSupport.scala:210-281`). That helper was written for record 
key lookups and accepts only `EqualTo`, `In`, and `And` of those. Any other 
filter falls to `case _ => (Option.empty, false)`, so no expression index query 
is found and both file pruning (`computeCandidateFileNames`) and partition 
pruning (`prunePartitions`) are skipped.
   
   `IN` has a second gap: its branch (`RecordLevelIndexSupport.scala:228-250`) 
only accepts a bare `AttributeReference`, while `EqualTo` goes through 
`getAttributeLiteralTuple`, which also unwraps a `Cast`. With `ts STRING`, 
`hour(ts)` is `hour(cast(ts as timestamp))`, so `hour(ts) = 16` prunes but 
`hour(ts) IN (16, 19)` does not.
   
   The stats filter compiler already handles ranges, so this looks limited to 
the extraction step (plus `composeIndexSchema`, which takes the stats type from 
the literal only for `EqualTo` and `In`).
   
   ### Repro
   
   ```sql
   CREATE TABLE hudi_table_expr_index (
       ts STRING, uuid STRING, rider STRING, driver STRING, fare DOUBLE, city 
STRING
   ) USING HUDI
   PARTITIONED BY (city)
   TBLPROPERTIES (
       primaryKey = 'uuid',
       preCombineField = 'ts',
       hoodie.metadata.index.column.stats.column.list = 'fare'
   );
   
   INSERT INTO hudi_table_expr_index VALUES
   ('2023-09-19 
23:40:49','334e26e9-8355-45cc-97c6-c31daf0df330','rider-A','driver-K',19.10,'san_francisco'),
   ('2023-09-18 
21:45:54','e96c4396-3fad-413a-a942-4cb36106d721','rider-C','driver-M',27.70,'san_francisco'),
   ('2023-09-18 
19:14:22','9909a8b1-2d15-4d3d-8ec9-efc48c536a00','rider-D','driver-L',33.90,'san_francisco'),
   ('2023-09-21 
16:34:26','1dced545-862b-4ceb-8b43-d2a568f6616b','rider-E','driver-O',93.50,'san_francisco'),
   ('2023-09-23 
09:42:17','e3cf430c-889d-4015-bc98-59bdce1e530c','rider-F','driver-P',34.15,'sao_paulo'),
   ('2023-09-22 
09:53:40','7a84095f-737f-40bc-b62f-6b69664712d2','rider-G','driver-Q',43.40,'sao_paulo'),
   ('2023-09-19 
02:38:07','3eeb61f7-c2b0-4636-99bd-5d7a5a1d2c04','rider-I','driver-S',41.06,'chennai'),
   ('2023-09-19 
01:33:19','c8abbe79-8d89-47ea-b4ce-4d224bae5bfa','rider-J','driver-T',17.85,'chennai');
   
   CREATE INDEX ts_hour ON hudi_table_expr_index USING column_stats(ts) 
options(expr='hour');
   
   SELECT city, _hoodie_file_name, fare FROM hudi_table_expr_index WHERE 
hour(ts) > 12;
   ```
   
   One base file per partition. `hour(ts)` ranges: chennai [1, 2], 
san_francisco [16, 23], sao_paulo [9, 9]. Files scanned (`numFiles` of the 
scan) with `hoodie.enable.data.skipping=true`, Spark 3.5, master `0b696f915b67`:
   
   | filter | files that can match | scanned, `ts STRING` | scanned, `ts 
TIMESTAMP` |
   | --- | --- | --- | --- |
   | `hour(ts) = 16` | 1 | 1 | 1 |
   | `hour(ts) IN (16, 19)` | 1 | 3 | 1 |
   | `hour(ts) > 12` | 1 | 3 | 3 |
   | `hour(ts) BETWEEN 12 AND 24` | 1 | 3 | 3 |
   | `hour(ts) >= 16` | 1 | 3 | 3 |
   | `hour(ts) < 5` | 1 | 3 | 3 |
   | `NOT hour(ts) <= 12` | 1 | 3 | 3 |
   
   Results are correct in every case; only pruning is lost.
   
   ### Suggested fix
   
   Give the expression index its own filter extraction instead of reusing the 
record key helper: accept binary comparisons on the indexed expression, unwrap 
a `Cast` on the source column for `In` as `EqualTo` already does, and derive 
the stats type in `composeIndexSchema` for comparisons too.
   
   Related: #20255 / #20256 (the same method matches filters on a different 
function of the column), #17489.
   


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

Reply via email to