Oracle: Column data histograms and the role of SYS.COL_USAGE$
In order for Oracle to create histogram-table statistics, the column needs to have participated in certain where clause predicates. If and which kind of predicates were used on a given column is recorded in sys.col_usage$.
This note attempts to demonstrate the interaction between col_usage$ and the statistic gathering process.
First, we create a table with 1 million records of skewed data:
Querying sys.col_usage$ reveals that no usages are recorded.
This is of course not surprising as no query took place on the table:
select
substr(col.name, 1, 8) col_name,
cou.equality_preds,
cou.equijoin_preds,
cou.nonequijoin_preds,
cou.range_preds,
cou.like_preds,
cou.null_preds,
cou.timestamp
from
sys.obj$ obj join
sys.col$ col on obj.obj# = col.obj# left join
sys.col_usage$ cou on col.obj# = cou.obj# and
col.col# = cou.intcol#
where
obj.owner# = sys_context('userenv', 'current_userid') and
obj.name = 'TQ84_COL_STATS';
--
-- COL_NAME EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP
-- -------- -------------- -------------- ----------------- ----------- ---------- ---------- -------------------
-- VAL_1
-- VAL_2
-- VAL_3
We're now executing a select statment using an equality predicate on val_2 and a range predicate on val_3:
select
count(*)
from
tq84_col_stats
where
val_2 = 1 or
val_3 < 2;
Gathering statistics again:
begin
dbms_stats.gather_table_stats(
user,
'tq84_col_stats',
method_opt => 'for all columns size auto'
);
end;
/
After gathering the statistics (which I presume to internally call dbms_stats.flush_database_monitoring_info), the data in sys.col_usage$ now shows that the table was queried using an equality predicate on val_2 and a range predicate on val_3: