1 row estimated on 19.13. I tried stats using
FOR ALL COLUMNS SIZE 255 and
FOR ALL COLUMNS SIZE 255 FOR COLUMNS SIZE 255 (day,hour) but they seem to behave the same. In the predicate info, you can see the DAY= filter is the problem.
RE: Why would we use both DAY and HOUR you ask. In larger queries where the time table is joining to both hourly and daily partitioned tables, we include hour= and day= as additional binds so the optimizer can use specific partition stats from those other tables. Also, we usually get a better plan because the optimizer knows immediately what range to use on each table vs. figuring it out based on the time table (which as we see here has issues).
RE: Our time table design. All our data is time-block based and streams in from upstream systems/vendors with a date. I get the theory and it's more space efficient but having the date in the table directly has so many benefits. I'm not even sure that's the root of the problem here.
Thank you. Maybe this is fixed in 19.25!! That will be my Christmas present!
SQL> set echo on autotrace off lines 200 pages 0
Autotrace Disabled
SQL> select version_full from v$instance;
19.13.0.0.0
SQL>
SQL> DROP TABLE tst_timetab;
Table TST_TIMETAB dropped.
SQL> create table tst_timetab (hour date, day date, month date, year date, primary key (hour) );
Table TST_TIMETAB created.
SQL>
SQL> insert into tst_timetab
2 select day+offset/24 hour, trunc(day+offset/24, 'dd') day, trunc(day+offset/24, 'mm') month, trunc(day+offset/24, 'yy') year
3 from (select to_date('1-jan-2020', 'dd-mon-yyyy') day, (level-1) offset from dual connect by level<=5*365*24);
43,800 rows inserted.
SQL> commit;
Commit complete.
SQL>
SQL> exec DBMS_STATS.GATHER_TABLE_STATS(user, 'tst_timetab', cascade=>true, method_opt => 'FOR ALL COLUMNS SIZE 255', no_invalidate=>false );
PL/SQL procedure successfully completed.
SQL>
SQL> set autotrace on
Autotrace Enabled
Shows the execution plan as well as statistics of the statement.
SQL> select /*+gather_plan_statistics*/ *
2 from tst_timetab
3 where day = to_date('20-jan-2022', 'dd-mon-yyyy')
4 and hour >= to_date('20-jan-2022', 'dd-mon-yyyy')
5 and hour < to_date('21-jan-2022', 'dd-mon-yyyy');
20-JAN-2022 00:00:00 20-JAN-2022 00:00:00 01-JAN-2022 00:00:00 01-JAN-2022 00:00:00
...
20-JAN-2022 23:00:00 20-JAN-2022 00:00:00 01-JAN-2022 00:00:00 01-JAN-2022 00:00:00
24 rows selected.
SQL_ID 3r8b9v6bb717w, child number 0
-------------------------------------
select /*+gather_plan_statistics*/ * from tst_timetab where day =
to_date('20-jan-2022', 'dd-mon-yyyy') and hour >=
to_date('20-jan-2022', 'dd-mon-yyyy') and hour <
to_date('21-jan-2022', 'dd-mon-yyyy')
Plan hash value: 1518437623
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 24 |00:00:00.01 | 3 |
|* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TST_TIMETAB | 1 | 1 | 24 |00:00:00.01 | 3 |
|* 2 | INDEX RANGE SCAN | SYS_C00432714 | 1 | 25 | 24 |00:00:00.01 | 2 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DAY"=TO_DATE(' 2022-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
2 - access("HOUR">=TO_DATE(' 2022-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "HOUR"<TO_DATE('
2022-01-21 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
Statistics
-----------------------------------------------------------
1 DB time
5 Requests to/from client
16384 cell physical IO interconnect bytes
5 consistent gets
3 consistent gets examination
2 consistent gets examination (fastpath)
5 consistent gets from cache
2 consistent gets pin
2 consistent gets pin (fastpath)
5 db block gets
5 db block gets from cache
4 db block gets from cache (fastpath)
3 enqueue releases
3 enqueue requests
1 messages sent
8 non-idle wait count
4 opened cursors cumulative
1 opened cursors current
1 physical read total IO requests
16384 physical read total bytes
1 pinned cursors current
3 recursive calls
10 session logical reads
6 user calls
SQL>
SQL> exec DBMS_STATS.GATHER_TABLE_STATS(user, 'tst_timetab', cascade=>true, method_opt => 'FOR ALL COLUMNS SIZE 255 FOR COLUMNS SIZE 255 (day,hour)', no_invalidate=>false );
PL/SQL procedure successfully completed.
SQL>
SQL> select /*+gather_plan_statistics*/ *
2 from tst_timetab
3 where day = to_date('20-jan-2022', 'dd-mon-yyyy')
4 and hour >= to_date('20-jan-2022', 'dd-mon-yyyy')
5 and hour < to_date('21-jan-2022', 'dd-mon-yyyy');
20-JAN-2022 00:00:00 20-JAN-2022 00:00:00 01-JAN-2022 00:00:00 01-JAN-2022 00:00:00
...
20-JAN-2022 23:00:00 20-JAN-2022 00:00:00 01-JAN-2022 00:00:00 01-JAN-2022 00:00:00
24 rows selected.
SQL_ID 3r8b9v6bb717w, child number 0
-------------------------------------
select /*+gather_plan_statistics*/ * from tst_timetab where day =
to_date('20-jan-2022', 'dd-mon-yyyy') and hour >=
to_date('20-jan-2022', 'dd-mon-yyyy') and hour <
to_date('21-jan-2022', 'dd-mon-yyyy')
Plan hash value: 1518437623
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 24 |00:00:00.01 | 3 |
|* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TST_TIMETAB | 1 | 1 | 24 |00:00:00.01 | 3 |
|* 2 | INDEX RANGE SCAN | SYS_C00432714 | 1 | 19 | 24 |00:00:00.01 | 2 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DAY"=TO_DATE(' 2022-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
2 - access("HOUR">=TO_DATE(' 2022-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "HOUR"<TO_DATE('
2022-01-21 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
Statistics
-----------------------------------------------------------
5 Requests to/from client
5 consistent gets
1 consistent gets examination
1 consistent gets examination (fastpath)
5 consistent gets from cache
4 consistent gets pin
4 consistent gets pin (fastpath)
1 enqueue releases
1 enqueue requests
5 non-idle wait count
3 opened cursors cumulative
1 opened cursors current
1 pinned cursors current
2 recursive calls
5 session logical reads
6 user calls