Commit 2447bc4c authored by Igor Babaev's avatar Igor Babaev

Addressed the following issue from the review of the patch for

engine-independent statistics.
When the primary key was dropped or changed statistics on secondary
indexes for the prefixes that included components of the primary 
key was not removed from the table mysql.index_stats.

Also fixed: in the some cases when a column was changed statistics
on the indexes that included this column was not removed from the
table mysql.index_stats.

Also disabled the test mdev-504 for --ps-protocol.
parent dd119466
......@@ -499,14 +499,9 @@ test t1 f 1 5 0.2000 1.0000 6.4000
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx1 1 6.4000
test t1 idx1 2 1.6875
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
test t1 idx4 1 6.2000
test t1 idx4 2 1.6875
test t1 idx4 3 1.1304
ALTER TABLE t1 CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
Table Create Table
......@@ -590,14 +585,9 @@ test t1 f 1 5 0.2000 1.0000 6.4000
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx4 3 1.1304
test t1 idx4 2 1.6875
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
test t1 idx4 1 6.2000
test t1 idx1 2 1.6875
test t1 idx1 1 6.4000
ALTER TABLE t1 CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
Table Create Table
......@@ -943,6 +933,7 @@ test t1 idx4 3 1.1304
CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ENGINE=InnoDB;
INSERT INTO t2 SELECT * FROM t1;
set optimizer_switch='extended_keys=off';
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 analyze status OK
......@@ -987,6 +978,142 @@ test t2 idx4 3 1.1304
DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
set optimizer_switch='extended_keys=on';
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 analyze status OK
SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t2 40
SELECT * FROM mysql.column_stats ORDER BY column_name;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
test t2 idx1 1 6.4000
test t2 idx1 2 1.6875
test t2 idx1 3 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx2 3 1.0000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 1.6875
test t2 idx4 3 1.1304
test t2 idx4 4 1.0000
ALTER TABLE t2 DROP PRIMARY KEY, DROP INDEX idx1;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx3 1 8.5000
test t2 idx4 1 6.2000
test t2 idx4 2 1.6875
test t2 idx4 3 1.1304
UPDATE t2 SET b=0 WHERE b IS NULL;
ALTER TABLE t2 ADD PRIMARY KEY (a,b);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx3 1 8.5000
test t2 idx4 1 6.2000
test t2 idx4 2 1.6875
test t2 idx4 3 1.1304
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
test t2 PRIMARY 2 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx2 3 1.0000
test t2 idx2 4 1.0000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx3 3 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 1.7222
test t2 idx4 3 1.1154
test t2 idx4 4 1.0000
ALTER TABLE t2 CHANGE COLUMN b b varchar(30);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx3 1 8.5000
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
test t2 PRIMARY 2 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx2 3 1.0000
test t2 idx2 4 1.0000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx3 3 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 1.7222
test t2 idx4 3 1.1154
test t2 idx4 4 1.0000
ALTER TABLE t2 CHANGE COLUMN b b varchar(32);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx3 1 8.5000
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
test t2 PRIMARY 2 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx2 3 1.0000
test t2 idx2 4 1.0000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx3 3 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 1.7222
test t2 idx4 3 1.1154
test t2 idx4 4 1.0000
ALTER TABLE t2 DROP COLUMN b;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx3 1 8.5000
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx2 3 1.0000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 2.2308
test t2 idx4 3 1.0000
set optimizer_switch='extended_keys=off';
ALTER TABLE t1
DROP INDEX idx1,
DROP INDEX idx4;
......@@ -994,11 +1121,34 @@ ALTER TABLE t1
MODIFY COLUMN b text,
ADD INDEX idx1 (b(4), e),
ADD INDEX idx4 (e, b(4), d);
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx2 3 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t2 idx4 3 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 2.2308
test t2 PRIMARY 1 1.0000
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
......@@ -1007,9 +1157,18 @@ test t1 f 1 5 0.2000 1.0000 6.4000
test t1 b NULL NULL 0.2000 17.1250 NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
test t2 idx3 1 8.5000
test t2 idx3 2 1.0000
test t2 idx2 3 1.0000
test t2 idx2 1 7.0000
test t2 idx2 2 2.3846
test t1 idx2 1 7.0000
test t1 idx3 1 8.5000
test t1 PRIMARY 1 1.0000
test t2 idx4 3 1.0000
test t2 idx4 1 6.2000
test t2 idx4 2 2.2308
test t2 PRIMARY 1 1.0000
test t1 idx2 2 2.3846
test t1 idx1 1 NULL
test t1 idx1 2 NULL
......@@ -1057,28 +1216,6 @@ test t1 idx1 2 NULL
test t1 idx4 1 6.2000
test t1 idx4 2 NULL
test t1 idx4 3 NULL
SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t1 b NULL NULL 0.2000 17.1250 NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx1 1 NULL
test t1 idx1 2 NULL
test t1 idx4 1 6.2000
test t1 idx4 2 NULL
test t1 idx4 3 NULL
DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
......
--disable_ps_protocol
CREATE TABLE A (
pk INTEGER AUTO_INCREMENT PRIMARY KEY,
fdate DATE
......
......@@ -368,22 +368,60 @@ SELECT * FROM mysql.table_stats;
SELECT * FROM mysql.column_stats;
SELECT * FROM mysql.index_stats;
CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ENGINE=InnoDB;
INSERT INTO t2 SELECT * FROM t1;
set optimizer_switch='extended_keys=off';
ANALYZE TABLE t2;
SELECT * FROM mysql.table_stats;
SELECT * FROM mysql.column_stats ORDER BY column_name;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
set optimizer_switch='extended_keys=on';
ANALYZE TABLE t2;
SELECT * FROM mysql.table_stats;
SELECT * FROM mysql.column_stats ORDER BY column_name;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ALTER TABLE t2 DROP PRIMARY KEY, DROP INDEX idx1;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
UPDATE t2 SET b=0 WHERE b IS NULL;
ALTER TABLE t2 ADD PRIMARY KEY (a,b);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ALTER TABLE t2 CHANGE COLUMN b b varchar(30);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ALTER TABLE t2 CHANGE COLUMN b b varchar(32);
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ALTER TABLE t2 DROP COLUMN b;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
set optimizer_switch='extended_keys=off';
ALTER TABLE t1
DROP INDEX idx1,
DROP INDEX idx4;
......@@ -392,6 +430,9 @@ ALTER TABLE t1
ADD INDEX idx1 (b(4), e),
ADD INDEX idx4 (e, b(4), d);
SELECT * FROM mysql.column_stats;
SELECT * FROM mysql.index_stats;
ANALYZE TABLE t1;
SELECT * FROM mysql.column_stats;
......@@ -411,7 +452,6 @@ SELECT * FROM mysql.index_stats;
set use_stat_tables='never';
ANALYZE TABLE t1 PERSISTENT FOR ALL;
SELECT * FROM mysql.table_stats;
......@@ -419,11 +459,6 @@ SELECT * FROM mysql.column_stats;
SELECT * FROM mysql.index_stats;
SELECT * FROM mysql.table_stats;
SELECT * FROM mysql.column_stats;
SELECT * FROM mysql.index_stats;
DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
......
......@@ -321,7 +321,8 @@ int alloc_statistics_for_table(THD *thd, TABLE *table);
int update_statistics_for_table(THD *thd, TABLE *table);
int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab);
int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col);
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info);
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
bool ext_prefixes_only);
int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
LEX_STRING *new_db, LEX_STRING *new_tab);
int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
......
......@@ -2660,6 +2660,9 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col)
tab The table the index belongs to
@param
key_info The descriptor of the index whose statistics is to be deleted
@param
ext_prefixes_only Delete statistics only on the index prefixes extended by
the components of the primary key
@details
The function delete statistics on the index specified by 'key_info'
......@@ -2675,7 +2678,8 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col)
definition of a column used in the definition of the index.
*/
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info)
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
bool ext_prefixes_only)
{
int err;
bool save_binlog_row_based;
......@@ -2702,14 +2706,29 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info)
stat_table= tables.table;
Index_stat index_stat(stat_table, tab);
index_stat.set_index_prefix_key_fields(key_info);
while (index_stat.find_next_stat_for_prefix(3))
if (!ext_prefixes_only)
{
err= index_stat.delete_stat();
if (err && !rc)
rc= 1;
index_stat.set_index_prefix_key_fields(key_info);
while (index_stat.find_next_stat_for_prefix(3))
{
err= index_stat.delete_stat();
if (err && !rc)
rc= 1;
}
}
else
{
for (uint i= key_info->key_parts; i < key_info->ext_key_parts; i++)
{
index_stat.set_key_fields(key_info, i+1);
if (index_stat.find_next_stat_for_prefix(4))
{
err= index_stat.delete_stat();
if (err && !rc)
rc= 1;
}
}
}
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
......
......@@ -5243,6 +5243,26 @@ mysql_compare_tables(TABLE *table,
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
if (!(tmp= field->is_equal(tmp_new_field)))
{
if (table->s->tmp_table == NO_TMP_TABLE)
{
KEY *key_info= table->key_info;
for (uint i=0; i < table->s->keys; i++, key_info++)
{
if (field->part_of_key.is_set(i))
{
uint key_parts= table->actual_n_key_parts(key_info);
for (uint j= 0; j < key_parts; j++)
{
if (key_info->key_part[j].fieldnr-1 == field->field_index)
{
(void) delete_statistics_for_index(thd, table, key_info,
j >= key_info->key_parts);
break;
}
}
}
}
}
DBUG_PRINT("info", ("!field_is_equal('%s') -> ALTER_TABLE_DATA_CHANGED",
new_field->field_name));
DBUG_RETURN(0);
......@@ -5342,7 +5362,20 @@ mysql_compare_tables(TABLE *table,
field->flags|= FIELD_IN_ADD_INDEX;
}
if (table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_index(thd, table, table_key);
{
(void) delete_statistics_for_index(thd, table, table_key, FALSE);
if (table_key - table->key_info == table->s->primary_key)
{
KEY *tab_key_info= table->key_info;
for (uint j=0; j < table->s->keys; j++, tab_key_info++)
{
if (tab_key_info->key_parts != tab_key_info->ext_key_parts)
(void) delete_statistics_for_index(thd, table, tab_key_info,
TRUE);
}
}
}
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
}
/*end of for (; table_key < table_key_end;) */
......@@ -5544,6 +5577,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
uint used_fields= create_info->used_fields;
KEY *key_info=table->key_info;
bool rc= TRUE;
bool modified_primary_key= FALSE;
Create_field *def;
Field **f_ptr,*field;
DBUG_ENTER("mysql_prepare_alter_table");
......@@ -5740,7 +5774,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Collect all keys which isn't in drop list. Add only those
for which some fields exists.
*/
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
{
char *key_name= key_info->name;
......@@ -5755,7 +5789,19 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (drop)
{
if (table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_index(thd, table, key_info);
{
(void) delete_statistics_for_index(thd, table, key_info, FALSE);
if (i == table->s->primary_key)
{
KEY *tab_key_info= table->key_info;
for (uint j=0; j < table->s->keys; j++, tab_key_info++)
{
if (tab_key_info->key_parts != tab_key_info->ext_key_parts)
(void) delete_statistics_for_index(thd, table, tab_key_info,
TRUE);
}
}
}
drop_it.remove();
continue;
}
......@@ -5786,6 +5832,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
if (!cfield)
{
if (table->s->primary_key == i)
modified_primary_key= TRUE;
delete_index_stat= TRUE;
continue; // Field is removed
}
......@@ -5830,8 +5878,15 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
strlen(cfield->field_name),
key_part_length));
}
if (delete_index_stat && table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_index(thd, table, key_info);
if (table->s->tmp_table == NO_TMP_TABLE)
{
if (delete_index_stat)
(void) delete_statistics_for_index(thd, table, key_info, FALSE);
else if (modified_primary_key &&
key_info->key_parts != key_info->ext_key_parts)
(void) delete_statistics_for_index(thd, table, key_info, TRUE);
}
if (key_parts.elements)
{
KEY_CREATE_INFO key_create_info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment