Commit 055477ae authored by Igor Babaev's avatar Igor Babaev

Support of the extended syntax for ANALYZE.

parent 2a1afc29
...@@ -219,6 +219,65 @@ WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL) ...@@ -219,6 +219,65 @@ WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3'; AS 'ARITY 3';
ARITY 1 ARITY 2 ARITY 3 ARITY 1 ARITY 2 ARITY 3
6.2000 1.6875 1.1304 6.2000 1.6875 1.1304
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS() INDEXES();
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
SELECT * FROM table_stat;
db_name table_name cardinality
test t1 40
SELECT * FROM column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
SELECT * FROM index_stat;
db_name table_name index_name prefix_arity avg_frequency
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(c,e,b) INDEXES(idx2,idx4);
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
SELECT * FROM table_stat;
db_name table_name cardinality
test t1 40
SELECT * FROM column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
SELECT * FROM index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx4 1 6.2000
test t1 idx4 2 1.6875
test t1 idx4 3 1.1304
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
SELECT * FROM table_stat;
db_name table_name cardinality
test t1 40
SELECT * FROM column_stat;
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 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
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
SELECT * FROM index_stat;
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
CREATE TABLE t2 LIKE t1; CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ENGINE=InnoDB; ALTER TABLE t2 ENGINE=InnoDB;
INSERT INTO t2 SELECT * FROM t1; INSERT INTO t2 SELECT * FROM t1;
......
...@@ -181,6 +181,30 @@ SELECT ...@@ -181,6 +181,30 @@ SELECT
WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL) WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3'; AS 'ARITY 3';
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS() INDEXES();
SELECT * FROM table_stat;
SELECT * FROM column_stat;
SELECT * FROM index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(c,e,b) INDEXES(idx2,idx4);
SELECT * FROM table_stat;
SELECT * FROM column_stat;
SELECT * FROM index_stat;
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
SELECT * FROM table_stat;
SELECT * FROM column_stat;
SELECT * FROM index_stat;
CREATE TABLE t2 LIKE t1; CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 ENGINE=InnoDB; ALTER TABLE t2 ENGINE=InnoDB;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "sql_acl.h" // *_ACL #include "sql_acl.h" // *_ACL
#include "sp.h" // Sroutine_hash_entry #include "sp.h" // Sroutine_hash_entry
#include "sql_parse.h" // check_table_access #include "sql_parse.h" // check_table_access
#include "strfunc.h"
#include "sql_admin.h" #include "sql_admin.h"
/* Prepare, run and cleanup for mysql_recreate_table() */ /* Prepare, run and cleanup for mysql_recreate_table() */
...@@ -628,16 +629,75 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -628,16 +629,75 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
} }
} }
result_code= compl_result_code= 0; result_code= compl_result_code= HA_ADMIN_OK;
if (operator_func != &handler::ha_analyze ||
thd->variables.optimizer_use_stat_tables < 3) if (operator_func == &handler::ha_analyze)
{
TABLE *tab= table->table;
Field **field_ptr= tab->field;
if (!lex->column_list)
{
uint fields= 0;
for ( ; *field_ptr; field_ptr++, fields++) ;
bitmap_set_prefix(tab->read_set, fields);
}
else
{
int pos;
LEX_STRING *column_name;
List_iterator_fast<LEX_STRING> it(*lex->column_list);
bitmap_clear_all(tab->read_set);
while ((column_name= it++))
{
if (tab->s->fieldnames.type_names == 0 ||
(pos= find_type(&tab->s->fieldnames, column_name->str,
column_name->length, 1)) <= 0)
{
compl_result_code= result_code= HA_ADMIN_INVALID;
break;
}
bitmap_set_bit(tab->read_set, --pos);
}
}
if (!lex->index_list)
{
tab->keys_in_use_for_query.init(tab->s->keys);
}
else
{
int pos;
LEX_STRING *index_name;
List_iterator_fast<LEX_STRING> it(*lex->index_list);
tab->keys_in_use_for_query.clear_all();
while ((index_name= it++))
{
if (tab->s->keynames.type_names == 0 ||
(pos= find_type(&tab->s->keynames, index_name->str,
index_name->length, 1)) <= 0)
{
compl_result_code= result_code= HA_ADMIN_INVALID;
break;
}
tab->keys_in_use_for_query.set_bit(--pos);
}
}
}
if (result_code == HA_ADMIN_OK &&
(operator_func != &handler::ha_analyze ||
thd->variables.optimizer_use_stat_tables < 3))
{ {
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name)); DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
result_code = (table->table->file->*operator_func)(thd, check_opt); result_code = (table->table->file->*operator_func)(thd, check_opt);
DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
} }
if (operator_func == &handler::ha_analyze && opt_with_stat_tables && if (compl_result_code == HA_ADMIN_OK &&
operator_func == &handler::ha_analyze && opt_with_stat_tables &&
thd->variables.optimizer_use_stat_tables > 0) thd->variables.optimizer_use_stat_tables > 0)
{ {
if (!(compl_result_code= if (!(compl_result_code=
......
...@@ -456,6 +456,8 @@ void lex_start(THD *thd) ...@@ -456,6 +456,8 @@ void lex_start(THD *thd)
lex->set_var_list.empty(); lex->set_var_list.empty();
lex->param_list.empty(); lex->param_list.empty();
lex->view_list.empty(); lex->view_list.empty();
lex->column_list= NULL;
lex->index_list= NULL;
lex->prepared_stmt_params.empty(); lex->prepared_stmt_params.empty();
lex->auxiliary_table_list.empty(); lex->auxiliary_table_list.empty();
lex->unit.next= lex->unit.master= lex->unit.next= lex->unit.master=
......
...@@ -2383,6 +2383,8 @@ struct LEX: public Query_tables_list ...@@ -2383,6 +2383,8 @@ struct LEX: public Query_tables_list
List<Item_func_set_user_var> set_var_list; // in-query assignment list List<Item_func_set_user_var> set_var_list; // in-query assignment list
List<Item_param> param_list; List<Item_param> param_list;
List<LEX_STRING> view_list; // view list (list of field names in view) List<LEX_STRING> view_list; // view list (list of field names in view)
List<LEX_STRING> *column_list; // list of column names (in ANALYZE)
List<LEX_STRING> *index_list; // list of index names (in ANALYZE)
/* /*
A stack of name resolution contexts for the query. This stack is used A stack of name resolution contexts for the query. This stack is used
at parse time to set local name resolution contexts for various parts at parse time to set local name resolution contexts for various parts
......
...@@ -1289,6 +1289,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) ...@@ -1289,6 +1289,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
{ {
table_field= *field_ptr; table_field= *field_ptr;
uint max_heap_table_size= thd->variables.max_heap_table_size; uint max_heap_table_size= thd->variables.max_heap_table_size;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
set_nulls_for_write_column_stat_values(table_field); set_nulls_for_write_column_stat_values(table_field);
table_field->nulls= 0; table_field->nulls= 0;
table_field->column_total_length= 0; table_field->column_total_length= 0;
...@@ -1306,8 +1308,6 @@ int collect_statistics_for_table(THD *thd, TABLE *table) ...@@ -1306,8 +1308,6 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
table_field->count_distinct= NULL; table_field->count_distinct= NULL;
} }
bitmap_set_all(table->read_set);
/* Perform a full table scan to collect statistics on 'table's columns */ /* Perform a full table scan to collect statistics on 'table's columns */
if (!(rc= file->ha_rnd_init(TRUE))) if (!(rc= file->ha_rnd_init(TRUE)))
{ {
...@@ -1319,6 +1319,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) ...@@ -1319,6 +1319,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
for (field_ptr= table->field; *field_ptr; field_ptr++) for (field_ptr= table->field; *field_ptr; field_ptr++)
{ {
table_field= *field_ptr; table_field= *field_ptr;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
if (table_field->is_null()) if (table_field->is_null())
table_field->nulls++; table_field->nulls++;
else else
...@@ -1357,6 +1359,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) ...@@ -1357,6 +1359,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
for (field_ptr= table->field; *field_ptr; field_ptr++) for (field_ptr= table->field; *field_ptr; field_ptr++)
{ {
table_field= *field_ptr; table_field= *field_ptr;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
table_field->write_stat.nulls_ratio= (double) table_field->nulls/rows; table_field->write_stat.nulls_ratio= (double) table_field->nulls/rows;
table_field->write_stat.avg_length= table_field->write_stat.avg_length=
(double) table_field->column_total_length / (rows-table_field->nulls); (double) table_field->column_total_length / (rows-table_field->nulls);
...@@ -1380,12 +1384,13 @@ int collect_statistics_for_table(THD *thd, TABLE *table) ...@@ -1380,12 +1384,13 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
if (!rc) if (!rc)
{ {
uint keys= table->s->keys ; uint key;
key_map::Iterator it(table->keys_in_use_for_query);
/* Collect statistics for indexes */ /* Collect statistics for indexes */
for (uint i= 0; i < keys; i++) while ((key= it++) != key_map::Iterator::BITMAP_END)
{ {
if ((rc= collect_statistics_for_index(table, i))) if ((rc= collect_statistics_for_index(table, key)))
break; break;
} }
} }
...@@ -1439,7 +1444,6 @@ int update_statistics_for_table(THD *thd, TABLE *table) ...@@ -1439,7 +1444,6 @@ int update_statistics_for_table(THD *thd, TABLE *table)
int err; int err;
int rc= 0; int rc= 0;
TABLE *stat_table; TABLE *stat_table;
uint keys= table->s->keys;
DBUG_ENTER("update_statistics_for_table"); DBUG_ENTER("update_statistics_for_table");
...@@ -1466,6 +1470,8 @@ int update_statistics_for_table(THD *thd, TABLE *table) ...@@ -1466,6 +1470,8 @@ int update_statistics_for_table(THD *thd, TABLE *table)
for (Field **field_ptr= table->field; *field_ptr; field_ptr++) for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{ {
Field *table_field= *field_ptr; Field *table_field= *field_ptr;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
restore_record(stat_table, s->default_values); restore_record(stat_table, s->default_values);
column_stat.set_key_fields(table_field); column_stat.set_key_fields(table_field);
err= column_stat.update_stat(); err= column_stat.update_stat();
...@@ -1475,12 +1481,13 @@ int update_statistics_for_table(THD *thd, TABLE *table) ...@@ -1475,12 +1481,13 @@ int update_statistics_for_table(THD *thd, TABLE *table)
/* Update the statistical table index_stat */ /* Update the statistical table index_stat */
stat_table= tables[INDEX_STAT].table; stat_table= tables[INDEX_STAT].table;
uint key;
key_map::Iterator it(table->keys_in_use_for_query);
Index_stat index_stat(stat_table, table); Index_stat index_stat(stat_table, table);
KEY *key_info, *key_info_end;
for (key_info= table->key_info, key_info_end= table->key_info+keys; while ((key= it++) != key_map::Iterator::BITMAP_END)
key_info < key_info_end; key_info++)
{ {
KEY *key_info= table->key_info+key;
uint key_parts= table->actual_n_key_parts(key_info); uint key_parts= table->actual_n_key_parts(key_info);
for (i= 0; i < key_parts; i++) for (i= 0; i < key_parts; i++)
{ {
......
...@@ -1593,7 +1593,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1593,7 +1593,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
show describe load alter optimize keycache preload flush show describe load alter optimize keycache preload flush
reset purge begin commit rollback savepoint release reset purge begin commit rollback savepoint release
slave master_def master_defs master_file_def slave_until_opts slave master_def master_defs master_file_def slave_until_opts
repair analyze check start checksum repair analyze
analyze_table_list analyze_table_elem_spec
opt_persistent_stat_clause persistent_stat_spec
persistent_column_stat_spec persistent_index_stat_spec
table_column_list table_index_list
check start checksum
field_list field_list_item field_spec kill column_def key_def field_list field_list_item field_spec kill column_def key_def
keycache_list keycache_list_or_parts assign_to_keycache keycache_list keycache_list_or_parts assign_to_keycache
assign_to_keycache_parts assign_to_keycache_parts
...@@ -7212,7 +7217,7 @@ analyze: ...@@ -7212,7 +7217,7 @@ analyze:
/* Will be overriden during execution. */ /* Will be overriden during execution. */
YYPS->m_lock_type= TL_UNLOCK; YYPS->m_lock_type= TL_UNLOCK;
} }
table_list analyze_table_list
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
LEX* lex= thd->lex; LEX* lex= thd->lex;
...@@ -7223,6 +7228,86 @@ analyze: ...@@ -7223,6 +7228,86 @@ analyze:
} }
; ;
analyze_table_list:
analyze_table_elem_spec
| analyze_table_list ',' analyze_table_elem_spec
;
analyze_table_elem_spec:
table_name opt_persistent_stat_clause
;
opt_persistent_stat_clause:
/* empty */
{}
| PERSISTENT_SYM FOR_SYM persistent_stat_spec
{}
;
persistent_stat_spec:
ALL
{}
| COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec
{}
persistent_column_stat_spec:
ALL {}
| '('
{
THD *thd= YYTHD;
LEX* lex= thd->lex;
lex->column_list= new List<LEX_STRING>;
if (lex->column_list == NULL)
MYSQL_YYABORT;
}
table_column_list
')'
;
persistent_index_stat_spec:
ALL {}
| '('
{
THD *thd= YYTHD;
LEX* lex= thd->lex;
lex->index_list= new List<LEX_STRING>;
if (lex->index_list == NULL)
MYSQL_YYABORT;
}
table_index_list
')'
;
table_column_list:
/* empty */
{}
| ident
{
Lex->column_list->push_back((LEX_STRING*)
sql_memdup(&$1, sizeof(LEX_STRING)));
}
| table_column_list ',' ident
{
Lex->column_list->push_back((LEX_STRING*)
sql_memdup(&$3, sizeof(LEX_STRING)));
}
;
table_index_list:
/* empty */
{}
| ident
{
Lex->index_list->push_back((LEX_STRING*)
sql_memdup(&$1, sizeof(LEX_STRING)));
}
| table_index_list ',' ident
{
Lex->index_list->push_back((LEX_STRING*)
sql_memdup(&$3, sizeof(LEX_STRING)));
}
;
binlog_base64_event: binlog_base64_event:
BINLOG_SYM TEXT_STRING_sys BINLOG_SYM TEXT_STRING_sys
{ {
......
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