Fix Bug#30423 "InnoDBs treatment of NULL in index stats causes bad

"rows examined" estimates". This change implements "innodb_stats_method"
with options of "nulls_equal", "nulls_unequal" and "null_ignored".
      
rb://553 approved by Marko
This commit is contained in:
Jimmy Yang 2011-01-14 09:02:28 -08:00
commit 9cd4d49840
25 changed files with 1157 additions and 77 deletions

View file

@ -404,7 +404,10 @@ btr_estimate_n_rows_in_range(
/***********************************************************************
Estimates the number of different key values in a given index, for
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
The estimates are stored in the array index->stat_n_diff_key_vals. */
The estimates are stored in the array index->stat_n_diff_key_vals.
If innodb_stats_method is nulls_ignored, we also record the number of
non-null values for each prefix and stored the estimates in
array index->stat_n_non_null_key_vals. */
void
btr_estimate_number_of_different_key_vals(

View file

@ -222,6 +222,12 @@ struct dict_index_struct{
for this index, for each n-column prefix
where n <= dict_get_n_unique(index); we
periodically calculate new estimates */
ib_longlong* stat_n_non_null_key_vals;
/* approximate number of non-null key values
for this index, for each column where
n < dict_get_n_unique(index); This
is used when innodb_stats_method is
"nulls_ignored". */
ulint stat_index_size;
/* approximate index size in database pages */
ulint stat_n_leaf_pages;

View file

@ -141,6 +141,10 @@ cmp_rec_rec_with_match(
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
ibool nulls_unequal,
/* in: TRUE if this is for index statistics
cardinality estimation, and innodb_stats_method
is "nulls_unequal" or "nulls_ignored" */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current

View file

@ -72,5 +72,5 @@ cmp_rec_rec(
ulint match_b = 0;
return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
&match_f, &match_b));
FALSE, &match_f, &match_b));
}

View file

@ -91,6 +91,11 @@ extern ulint srv_lock_table_size;
extern ulint srv_n_file_io_threads;
/* The "innodb_stats_method" setting, decides how InnoDB is going
to treat NULL value when collecting statistics. It is not defined
as enum type because the configure option takes unsigned integer type. */
extern ulong srv_innodb_stats_method;
#ifdef UNIV_LOG_ARCHIVE
extern ibool srv_log_archive_on;
extern ibool srv_archive_recovery;
@ -286,6 +291,19 @@ of lower numbers are included. */
#define SRV_FORCE_NO_LOG_REDO 6 /* do not do the log roll-forward
in connection with recovery */
/* Alternatives for srv_innodb_stats_method, which could be changed by
setting innodb_stats_method */
enum srv_stats_method_name_enum {
SRV_STATS_NULLS_EQUAL, /* All NULL values are treated as
equal. This is the default setting
for innodb_stats_method */
SRV_STATS_NULLS_UNEQUAL, /* All NULL values are treated as
NOT equal. */
SRV_STATS_NULLS_IGNORED /* NULL values are ignored */
};
typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
/*************************************************************************
Boots Innobase server. */