Skip to content

Commit 44ed67d

Browse files
MDEV-36761 Implement NULL-aware cardinality estimation for indexed columns
(Preparation for the main patch) set_statistics_for_table() incorrectly treated indexes with all NULL values the same as indexes with no statistics, because avg_frequency is 0 in both cases. This caused the optimizer to ignore valid EITS data and fall back to engine statistics. Additionally, KEY::actual_rec_per_key() would fall back to engine statistics even when EITS was available, and used incorrect pointer comparison (rec_per_key == 0 instead of nullptr). Fix by adding Index_statistics::stats_were_read flag to track per-index whether statistics were actually read from persistent tables, and restructuring actual_rec_per_key() to prioritize EITS when available.
1 parent 5cf9d84 commit 44ed67d

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

sql/sql_statistics.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3120,7 +3120,10 @@ read_statistics_for_table(THD *thd, TABLE *table,
31203120
found|= index_stat.get_stat_values(index_statistics);
31213121
}
31223122
if (found)
3123+
{
31233124
new_stats_cb->stats_available|= TABLE_STAT_INDEX;
3125+
index_statistics->mark_stats_as_read();
3126+
}
31243127

31253128
key_part_map ext_key_part_map= key_info->ext_key_part_map;
31263129
if (key_info->user_defined_key_parts != key_info->ext_key_parts &&
@@ -4157,7 +4160,7 @@ void set_statistics_for_table(THD *thd, TABLE *table)
41574160
(check_eits_preferred(thd) &&
41584161
table->stats_is_read &&
41594162
key_info->read_stats->avg_frequency_is_inited() &&
4160-
key_info->read_stats->get_avg_frequency(0) > 0.5);
4163+
key_info->read_stats->has_stats());
41614164
}
41624165
}
41634166

sql/sql_statistics.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,10 +603,19 @@ class Index_statistics
603603
k-component prefixes among them
604604
*/
605605
ulonglong *avg_frequency;
606+
bool stats_were_read;
606607

607608
public:
608609

609-
void init_avg_frequency(ulonglong *ptr) { avg_frequency= ptr; }
610+
void init_avg_frequency(ulonglong *ptr)
611+
{
612+
avg_frequency= ptr;
613+
stats_were_read= false;
614+
}
615+
616+
void mark_stats_as_read() { stats_were_read= true; }
617+
618+
bool has_stats() const { return stats_were_read; }
610619

611620
bool avg_frequency_is_inited() { return avg_frequency != NULL; }
612621

sql/table.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10299,10 +10299,15 @@ uint TABLE_SHARE::actual_n_key_parts(THD *thd)
1029910299

1030010300
double KEY::actual_rec_per_key(uint i) const
1030110301
{
10302-
if (rec_per_key == 0)
10303-
return 0;
10304-
return (is_statistics_from_stat_tables ?
10305-
read_stats->get_avg_frequency(i) : (double) rec_per_key[i]);
10302+
if (is_statistics_from_stat_tables)
10303+
{
10304+
// Use engine-independent statistics (EITS)
10305+
return read_stats->get_avg_frequency(i);
10306+
}
10307+
// Fall back to engine-dependent statistics if EITS is not available
10308+
if (rec_per_key == nullptr)
10309+
return 0; // No statistics available
10310+
return (double) rec_per_key[i];
1030610311
}
1030710312

1030810313
/*

0 commit comments

Comments
 (0)