Commit 47fae7f0 authored by Igor Babaev's avatar Igor Babaev

Added procedures to delete records by keys from statistical tables.

Now when a table is dropped the statistics on the table is removed 
from the statistical tables. If the table is altered in such a way
that a column is dropped or the type of the column is changed then
statistics on the column is removed from the table column_stat.
It also triggers removal of the statistics on the indexes who use
this column as its component.

Added procedures that changes the names of the tables or columns
in the statistical tables for. 
These procedures are used when tables/columns are renamed.

Also partly re-factored the code that introduced the persistent
statistical tables.

Added test cases into statistics.test to cover the new code.
parent 4a6a0830
......@@ -12,10 +12,10 @@ d date,
e double,
f bit(3),
INDEX idx1 (b, e),
INDEX idx2(c, d),
INDEX idx2 (c, d),
INDEX idx3 (d),
INDEX idx4 (e, b, d)
);
) ENGINE= MYISAM;
INSERT INTO t1 VALUES
(0, NULL, NULL, NULL, NULL, NULL),
(7, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'dddddddd', '1990-05-15', 0.1, b'100'),
......@@ -206,6 +206,662 @@ WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3';
ARITY 1 ARITY 2 ARITY 3
6.2000 1.6875 1.1304
CREATE TABLE t3 (
a int NOT NULL PRIMARY KEY,
b varchar(32),
c char(16),
INDEX idx (c)
) ENGINE=MYISAM;
INSERT INTO t3 VALUES
(0, NULL, NULL),
(7, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'dddddddd'),
(17, 'vvvvvvvvvvvvv', 'aaaa'),
(1, 'vvvvvvvvvvvvv', NULL),
(12, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'),
(23, 'vvvvvvvvvvvvv', 'dddddddd'),
(8, 'vvvvvvvvvvvvv', 'aaaa'),
(22, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'aaaa'),
(31, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'aaaa'),
(10, NULL, 'aaaa'),
(5, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'),
(15, 'vvvvvvvvvvvvv', 'ccccccccc'),
(30, NULL, 'bbbbbb'),
(38, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb'),
(18, 'zzzzzzzzzzzzzzzzzz', 'ccccccccc'),
(9, 'yyy', 'bbbbbb'),
(29, 'vvvvvvvvvvvvv', 'dddddddd');
ANALYZE TABLE t3;
Table Op Msg_type Msg_text
test.t3 analyze status OK
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test t1 40
test t3 17
SELECT * FROM mysql.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
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
SELECT * FROM mysql.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
test t3 PRIMARY 1 1.0000
test t3 idx 1 3.7500
ALTER TABLE t1 RENAME TO s1;
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test s1 40
test t3 17
SELECT * FROM mysql.column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test s1 a 0 49 0.0000 4.0000 1.0000
test s1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test s1 e 0.01 0.112 0.2250 8.0000 6.2000
test s1 f 1 5 0.2000 1.0000 6.4000
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test s1 PRIMARY 1 1.0000
test s1 idx1 1 6.4000
test s1 idx1 2 1.6875
test s1 idx2 1 7.0000
test s1 idx2 2 2.3846
test s1 idx3 1 8.5000
test s1 idx4 1 6.2000
test s1 idx4 2 1.6875
test s1 idx4 3 1.1304
test t3 PRIMARY 1 1.0000
test t3 idx 1 3.7500
RENAME TABLE s1 TO t1;
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test t1 40
test t3 17
SELECT * FROM mysql.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
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
SELECT * FROM mysql.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
test t3 PRIMARY 1 1.0000
test t3 idx 1 3.7500
DROP TABLE t3;
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.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 mysql.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 TEMPORARY TABLE t0 (
a int NOT NULL PRIMARY KEY,
b varchar(32)
);
INSERT INTO t0 SELECT a,b FROM t1;
ALTER TABLE t1 CHANGE COLUMN b x varchar(32),
CHANGE COLUMN e y double;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`x` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`y` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`x`,`y`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`y`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 x 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 y 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
ALTER TABLE t1 CHANGE COLUMN x b varchar(32),
CHANGE COLUMN y e double;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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
ALTER TABLE t1 RENAME TO s1, CHANGE COLUMN b x varchar(32);
SHOW CREATE TABLE s1;
Table Create Table
s1 CREATE TABLE `s1` (
`a` int(11) NOT NULL,
`x` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`x`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test s1 40
SELECT * FROM mysql.column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test s1 a 0 49 0.0000 4.0000 1.0000
test s1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test s1 e 0.01 0.112 0.2250 8.0000 6.2000
test s1 f 1 5 0.2000 1.0000 6.4000
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test s1 PRIMARY 1 1.0000
test s1 idx1 1 6.4000
test s1 idx1 2 1.6875
test s1 idx2 1 7.0000
test s1 idx2 2 2.3846
test s1 idx3 1 8.5000
test s1 idx4 1 6.2000
test s1 idx4 2 1.6875
test s1 idx4 3 1.1304
ALTER TABLE s1 RENAME TO t1, CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.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 mysql.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
ALTER TABLE t1 CHANGE COLUMN b x varchar(30);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`x` varchar(30) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`x`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.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
ALTER TABLE t1 CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.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 mysql.index_stat;
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
SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/save_column_stat'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
FROM mysql.column_stat WHERE column_name='b';
SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/save_index_stat'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
FROM mysql.index_stat WHERE index_name IN ('idx1', 'idx4');
ALTER TABLE t1 CHANGE COLUMN b x varchar(30);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`x` varchar(30) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`x`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
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
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(32) DEFAULT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stat'
INTO TABLE mysql.column_stat
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_index_stat'
INTO TABLE mysql.index_stat
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
SELECT * FROM mysql.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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx4 3 1.1304
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
test t1 idx4 2 1.6875
test t1 idx4 1 6.2000
test t1 idx1 2 1.6875
test t1 idx1 1 6.4000
ALTER TABLE t1 DROP COLUMN b;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`e`),
KEY `idx2` (`c`,`d`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx2 1 7.0000
test t1 idx2 2 2.3846
test t1 idx3 1 8.5000
DROP INDEX idx2 ON t1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx1` (`e`),
KEY `idx3` (`d`),
KEY `idx4` (`e`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
DROP INDEX idx1 ON t1;
DROP INDEX idx4 ON t1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx3` (`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
ALTER TABLE t1 ADD COLUMN b varchar(32);
CREATE INDEX idx1 ON t1(b, e);
CREATE INDEX idx2 ON t1(c, d);
CREATE INDEX idx4 ON t1(e, b, d);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
`b` varchar(32) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx3` (`d`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.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 NULL NULL 1.0000 NULL NULL
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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx2 1 7.0000
test t1 idx1 2 NULL
test t1 idx1 1 NULL
test t1 idx3 1 8.5000
test t1 idx2 2 2.3846
test t1 idx4 1 6.2000
test t1 idx4 2 NULL
test t1 idx4 3 NULL
UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a);
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx2 1 7.0000
test t1 idx1 2 1.6875
test t1 idx1 1 6.4000
test t1 idx3 1 8.5000
test t1 idx2 2 2.3846
test t1 idx4 1 6.2000
test t1 idx4 2 1.6875
test t1 idx4 3 1.1304
ALTER TABLE t1 DROP COLUMN b,
DROP INDEX idx1, DROP INDEX idx2, DROP INDEX idx4;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx3` (`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
ALTER TABLE t1 ADD COLUMN b varchar(32);
ALTER TABLE t1
ADD INDEX idx1 (b, e), ADD INDEX idx2 (c, d), ADD INDEX idx4 (e, b, d);
UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`c` char(16) DEFAULT NULL,
`d` date DEFAULT NULL,
`e` double DEFAULT NULL,
`f` bit(3) DEFAULT NULL,
`b` varchar(32) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `idx3` (`d`),
KEY `idx1` (`b`,`e`),
KEY `idx2` (`c`,`d`),
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.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 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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.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 mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx4 1 6.2000
test t1 idx4 2 1.6875
test t1 idx3 1 8.5000
test t1 idx2 2 2.3846
test t1 idx2 1 7.0000
test t1 idx1 2 1.6875
test t1 idx1 1 6.4000
test t1 idx4 3 1.1304
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
......@@ -227,9 +883,9 @@ db_name table_name cardinality
test t1 40
SELECT * FROM mysql.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
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 idx2 1 7.0000
......@@ -249,19 +905,19 @@ test t1 40
SELECT * FROM mysql.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
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
test t1 idx3 1 8.5000
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
......@@ -325,17 +981,17 @@ test.t1 analyze status OK
SELECT * FROM mysql.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 NULL NULL 0.2000 17.1250 NULL
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_stat;
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 idx3 1 8.5000
test t1 idx1 1 NULL
test t1 idx1 2 NULL
test t1 idx4 1 6.2000
......@@ -503,7 +1159,42 @@ WORLD_INNODB COUNTRYLANGUAGE PRIMARY 2 1.0000
WORLD_INNODB COUNTRYLANGUAGE Percentage 1 2.7640
use test;
DROP DATABASE world;
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
world_innodb Country 239
world_innodb City 4079
world_innodb CountryLanguage 984
SELECT * FROM mysql.column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
world_innodb Country Code ABW ZWE 0.0000 3.0000 1.0000
world_innodb Country Name Afghanistan Zimbabwe 0.0000 10.1088 1.0000
world_innodb Country SurfaceArea 0.40 17075400.00 0.0000 4.0000 1.0042
world_innodb Country Population 0 1277558000 0.0000 4.0000 1.0575
world_innodb Country Capital 1 4074 0.0293 4.0000 1.0000
world_innodb City ID 1 4079 0.0000 4.0000 1.0000
world_innodb City Name A Coruña (La Coruña) Ürgenc 0.0000 8.6416 1.0195
world_innodb City Country ABW ZWE 0.0000 3.0000 17.5819
world_innodb City Population 42 10500000 0.0000 4.0000 1.0467
world_innodb CountryLanguage Country ABW ZWE 0.0000 3.0000 4.2232
world_innodb CountryLanguage Language Abhyasi [South]Mande 0.0000 7.1778 2.1532
world_innodb CountryLanguage Percentage 0.0 99.9 0.0000 4.0000 2.7640
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
world_innodb Country PRIMARY 1 1.0000
world_innodb Country Name 1 1.0000
world_innodb City PRIMARY 1 1.0000
world_innodb City Population 1 1.0467
world_innodb City Country 1 17.5819
world_innodb CountryLanguage PRIMARY 1 4.2232
world_innodb CountryLanguage PRIMARY 2 1.0000
world_innodb CountryLanguage Percentage 1 2.7640
DROP DATABASE world_innodb;
SELECT * FROM mysql.table_stat;
db_name table_name cardinality
SELECT * FROM mysql.column_stat;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
SELECT * FROM mysql.index_stat;
db_name table_name index_name prefix_arity avg_frequency
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
......
......@@ -107,7 +107,7 @@ Handler_mrr_key_refills 0
Handler_mrr_rowid_refills 0
Handler_prepare 18
Handler_read_first 0
Handler_read_key 3
Handler_read_key 9
Handler_read_last 0
Handler_read_next 0
Handler_read_prev 0
......@@ -123,7 +123,7 @@ Handler_update 5
Handler_write 7
select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key";
handler_read_key
3
9
set @@global.userstat=0;
select * from information_schema.index_statistics;
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
......
......@@ -17,6 +17,7 @@ substring(object_name, locate("no_index_tab", object_name)) as short_name
from performance_schema.events_waits_history_long
where operation not like "tell"
and event_name like "wait/io/file/myisam/%"
having short_name <> ""
order by thread_id, event_id;
event_name short_source operation number_of_bytes short_name
wait/io/file/myisam/kfile mi_create.c: create NULL no_index_tab.MYI
......
......@@ -46,6 +46,7 @@ select event_name,
from performance_schema.events_waits_history_long
where operation not like "tell"
and event_name like "wait/io/file/myisam/%"
having short_name <> ""
order by thread_id, event_id;
# In case of failures, this will tell if file io are lost.
......
......@@ -20,10 +20,10 @@ CREATE TABLE t1 (
e double,
f bit(3),
INDEX idx1 (b, e),
INDEX idx2(c, d),
INDEX idx2 (c, d),
INDEX idx3 (d),
INDEX idx4 (e, b, d)
);
) ENGINE= MYISAM;
INSERT INTO t1 VALUES
(0, NULL, NULL, NULL, NULL, NULL),
......@@ -165,6 +165,180 @@ SELECT
WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3';
CREATE TABLE t3 (
a int NOT NULL PRIMARY KEY,
b varchar(32),
c char(16),
INDEX idx (c)
) ENGINE=MYISAM;
INSERT INTO t3 VALUES
(0, NULL, NULL),
(7, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'dddddddd'),
(17, 'vvvvvvvvvvvvv', 'aaaa'),
(1, 'vvvvvvvvvvvvv', NULL),
(12, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'),
(23, 'vvvvvvvvvvvvv', 'dddddddd'),
(8, 'vvvvvvvvvvvvv', 'aaaa'),
(22, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'aaaa'),
(31, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'aaaa'),
(10, NULL, 'aaaa'),
(5, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'),
(15, 'vvvvvvvvvvvvv', 'ccccccccc'),
(30, NULL, 'bbbbbb'),
(38, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb'),
(18, 'zzzzzzzzzzzzzzzzzz', 'ccccccccc'),
(9, 'yyy', 'bbbbbb'),
(29, 'vvvvvvvvvvvvv', 'dddddddd');
ANALYZE TABLE t3;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 RENAME TO s1;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
RENAME TABLE s1 TO t1;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
DROP TABLE t3;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
CREATE TEMPORARY TABLE t0 (
a int NOT NULL PRIMARY KEY,
b varchar(32)
);
INSERT INTO t0 SELECT a,b FROM t1;
ALTER TABLE t1 CHANGE COLUMN b x varchar(32),
CHANGE COLUMN e y double;
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
ALTER TABLE t1 CHANGE COLUMN x b varchar(32),
CHANGE COLUMN y e double;
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
ALTER TABLE t1 RENAME TO s1, CHANGE COLUMN b x varchar(32);
SHOW CREATE TABLE s1;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE s1 RENAME TO t1, CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 CHANGE COLUMN b x varchar(30);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx4);
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval
SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/save_column_stat'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
FROM mysql.column_stat WHERE column_name='b';
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval
SELECT * INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/save_index_stat'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
FROM mysql.index_stat WHERE index_name IN ('idx1', 'idx4');
ALTER TABLE t1 CHANGE COLUMN b x varchar(30);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 CHANGE COLUMN x b varchar(32);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval
LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/save_column_stat'
INTO TABLE mysql.column_stat
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval
LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/save_index_stat'
INTO TABLE mysql.index_stat
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
remove_file $MYSQLTEST_VARDIR/tmp/save_column_stat;
remove_file $MYSQLTEST_VARDIR/tmp/save_index_stat;
ALTER TABLE t1 DROP COLUMN b;
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
DROP INDEX idx2 ON t1;
SHOW CREATE TABLE t1;
SELECT * FROM mysql.index_stat;
DROP INDEX idx1 ON t1;
DROP INDEX idx4 ON t1;
SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD COLUMN b varchar(32);
CREATE INDEX idx1 ON t1(b, e);
CREATE INDEX idx2 ON t1(c, d);
CREATE INDEX idx4 ON t1(e, b, d);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a);
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 DROP COLUMN b,
DROP INDEX idx1, DROP INDEX idx2, DROP INDEX idx4;
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ALTER TABLE t1 ADD COLUMN b varchar(32);
ALTER TABLE t1
ADD INDEX idx1 (b, e), ADD INDEX idx2 (c, d), ADD INDEX idx4 (e, b, d);
UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a);
SHOW CREATE TABLE t1;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
DELETE FROM mysql.index_stat;
......@@ -297,7 +471,14 @@ SELECT UPPER(db_name), UPPER(table_name),
use test;
DROP DATABASE world;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
DROP DATABASE world_innodb;
SELECT * FROM mysql.table_stat;
SELECT * FROM mysql.column_stat;
SELECT * FROM mysql.index_stat;
DELETE FROM mysql.table_stat;
DELETE FROM mysql.column_stat;
......
......@@ -9649,6 +9649,7 @@ unlock_tables_n_open_system_tables_for_write(THD *thd,
DBUG_ENTER("unlock_tables_n_open_system_tables_for_write");
if (thd->lock)
mysql_unlock_tables(thd, thd->lock);
thd->lock= 0;
......
......@@ -315,6 +315,13 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
int read_statistics_for_table(THD *thd, TABLE *table);
int collect_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 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,
const char *new_name);
void set_statistics_for_table(THD *thd, TABLE *table);
extern "C" int simple_raw_key_cmp(void* arg, const void* key1,
......
......@@ -825,6 +825,17 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
lock_db_routines(thd, db))
goto exit;
if (!in_bootstrap)
{
for (table= tables; table; table= table->next_local)
{
LEX_STRING db_name= { table->db, table->db_length };
LEX_STRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY || !find_temporary_table(thd, table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
}
}
/* mysql_ha_rm_tables() requires a non-null TABLE_LIST. */
if (tables)
mysql_ha_rm_tables(thd, tables);
......
......@@ -279,6 +279,12 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
ren_table->db, old_alias,
new_db, new_alias, 0)))
{
LEX_STRING db_name= { ren_table->db, ren_table->db_length };
LEX_STRING table_name= { ren_table->table_name,
ren_table->table_name_length };
LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) };
(void) rename_table_in_stat_tables(thd, &db_name, &table_name,
&db_name, &new_table);
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
old_alias,
ren_table->table_name,
......
......@@ -57,16 +57,20 @@
static const uint STATISTICS_TABLES= 3;
/*
The names of the statistical tables in this list must correspond the
The names of the statistical tables in this array must correspond the
definitions of the tables in the file ../scripts/mysql_system_tables.sql
*/
static const char *STAT_TABLE_NAME[STATISTICS_TABLES]=
static const LEX_STRING stat_table_name[STATISTICS_TABLES]=
{
"table_stat",
"column_stat",
"index_stat"
{ C_STRING_WITH_LEN("table_stat") },
{ C_STRING_WITH_LEN("column_stat") },
{ C_STRING_WITH_LEN("index_stat") }
};
/* Name of database to which the statistical tables belong */
static const LEX_STRING stat_tables_db_name= { C_STRING_WITH_LEN("mysql") };
/**
@details
The function builds a list of TABLE_LIST elements for system statistical
......@@ -74,6 +78,7 @@ static const char *STAT_TABLE_NAME[STATISTICS_TABLES]=
The lock type of each element is set to TL_READ if for_write = FALSE,
otherwise it is set to TL_WRITE.
*/
inline void init_table_list_for_stat_tables(TABLE_LIST *tables, bool for_write)
{
uint i;
......@@ -82,21 +87,48 @@ inline void init_table_list_for_stat_tables(TABLE_LIST *tables, bool for_write)
for (i= 0; i < STATISTICS_TABLES; i++)
{
tables[i].db= (char*) "mysql";
tables[i].table_name= (char *) STAT_TABLE_NAME[i];
tables[i].alias= tables[i].table_name;
tables[i].db= stat_tables_db_name.str;
tables[i].db_length= stat_tables_db_name.length;
tables[i].alias= tables[i].table_name= stat_table_name[i].str;
tables[i].table_name_length= stat_table_name[i].length;
tables[i].lock_type= for_write ? TL_WRITE : TL_READ;
if (i < STATISTICS_TABLES - 1)
tables[i].next_global= tables[i].next_local=
tables[i].next_name_resolution_table= &tables[i+1];
if (i != 0)
tables[i].prev_global= &tables[i-1].next_global;
}
}
/**
@details
The function builds a TABLE_LIST containing only one element 'tbl' for
the statistical table called 'stat_tab_name'.
The lock type of the element is set to TL_READ if for_write = FALSE,
otherwise it is set to TL_WRITE.
*/
inline void init_table_list_for_single_stat_table(TABLE_LIST *tbl,
const LEX_STRING *stat_tab_name,
bool for_write)
{
bzero((char *) tbl, sizeof(TABLE_LIST));
tbl->db= stat_tables_db_name.str;
tbl->db_length= stat_tables_db_name.length;
tbl->alias= tbl->table_name= stat_tab_name->str;
tbl->table_name_length= stat_tab_name->length;
tbl->lock_type= for_write ? TL_WRITE : TL_READ;
}
/**
@details
The function sets null bits stored in the bitmap table_field->write_stat
for all statistical values collected for a column.
*/
inline void set_nulls_for_write_column_stat_values(Field *table_field)
{
table_field->write_stat.column_stat_nulls=
......@@ -104,11 +136,13 @@ inline void set_nulls_for_write_column_stat_values(Field *table_field)
(COLUMN_STAT_COLUMN_NAME+1);
}
/**
@details
The function sets null bits stored in the bitmap table_field->read_stat
for all statistical values collected for a column.
*/
inline void set_nulls_for_read_column_stat_values(Field *table_field)
{
table_field->read_stat.column_stat_nulls=
......@@ -116,50 +150,60 @@ inline void set_nulls_for_read_column_stat_values(Field *table_field)
(COLUMN_STAT_COLUMN_NAME+1);
}
/**
@details
The function removes the null bit stored in the bitmap
table_field->write_stat for the statistical value collected
on the statistical column number stat_field_no.
*/
inline void set_not_null_for_write_column_stat_value(Field *table_field,
uint stat_field_no)
{
table_field->write_stat.column_stat_nulls&= ~(1 << stat_field_no);
}
/**
@details
The function removes the null bit stored in the bitmap
table_field->read_stat for the statistical value collected
on the statistical column number stat_field_no.
*/
inline void set_not_null_for_read_column_stat_value(Field *table_field,
uint stat_field_no)
{
table_field->read_stat.column_stat_nulls&= ~(1 << stat_field_no);
}
/**
@details
The function checks the null bit stored in the bitmap
table_field->read_stat for the statistical value collected
on the statistical column number stat_field_no.
*/
inline bool check_null_for_write_column_stat_value(Field *table_field,
uint stat_field_no)
{
return table_field->write_stat.column_stat_nulls & (1 << stat_field_no);
}
/*
Stat_table is the base class for classes Table_stat, Column_stat and
Index_stat. The methods of these classes allow us table to read
statistical data from statistical tables and write collected statistical
data into statistical data. Objects of the classes Table_stat, Column_stat
and Index stat are used for reading/writing statistics from/into
persistent tables table_stat, column_stat and index_stat correspondingly.
These tables are stored in the system database 'mysql'.
Index_stat. The methods of these classes allow us to read statistical
data from statistical tables, write collected statistical data into
statistical tables and update statistical data in these tables
as well as update access fields belonging to the primary key and
delete records by prefixes of the primary key.
Objects of the classes Table_stat, Column_stat and Index stat are used
for reading/writing statistics from/into persistent tables table_stat,
column_stat and index_stat correspondingly. These tables are stored in
the system database 'mysql'.
Statistics is read and written always for a given database table t. When
an object of any of these classes is created a pointer to the TABLE
......@@ -168,9 +212,15 @@ inline bool check_null_for_write_column_stat_value(Field *table_field,
the corresponding statistical table st. So construction of an object to
read/write statistical data on table t from/into statistical table st
requires both table t and st to be opened.
In some cases the TABLE structure for table t may be undefined. Then
the objects of the classes Table_stat, Column_stat and Index stat are
created by the alternative constructor that require only the name
of the table t and the name of the database it belongs to. Now the
alternative constructors are used only in the cases when some records
belonging to the table are to be deleted, or its keys are to be updated
Reading/writing statistical data from/into a statistical table is always
performed by key. At the moment there is only one key defined for each
performed by a key. At the moment there is only one key defined for each
statistical table and this key is primary.
The primary key for the table table_stat is built as (db_name, table_name).
The primary key for the table column_stat is built as (db_name, table_name,
......@@ -234,7 +284,7 @@ inline bool check_null_for_write_column_stat_value(Field *table_field,
It is assumed that before any invocation of this method a call of the
function st.set_key_fields has set the values of the primary key fields
that serve to locate the row from the statistical table st where the
the colected statistical data from internal structures are to be written
the collected statistical data from internal structures are to be written
to. The statistical data is written from the counterparts of the
statistical fields of internal structures into which it would be read
by the functions get_stat_values. The counterpart fields are used
......@@ -248,29 +298,62 @@ inline bool check_null_for_write_column_stat_value(Field *table_field,
class Stat_table
{
private:
/* Handler used for the retrieval of the statistical table stat_table */
handler *stat_file;
KEY *stat_key_info; /* Structure for the index to access stat_table */
uint stat_key_length; /* Length of the key to access stat_table */
uchar *record[2]; /* Record buffers used to access/update stat_table */
uint stat_key_idx; /* The number of the key to access stat_table */
/* This is a helper function used only by the Stat_table constructors */
void common_init_stat_table()
{
stat_file= stat_table->file;
/* Currently any statistical table has only one key */
stat_key_idx= 0;
stat_key_info= &stat_table->key_info[stat_key_idx];
stat_key_length= stat_key_info->key_length;
record[0]= stat_table->record[0];
record[1]= stat_table->record[1];
}
protected:
/* Statistical table to read statistics from or to update */
/* Statistical table to read statistics from or to update/delete */
TABLE *stat_table;
KEY *stat_key_info; /* Structure for the index to access stat_table */
/* Table for which statistical data is read / updated */
TABLE *table;
char *db_name; /* Name of the database containing 'table' */
uint db_name_len; /* Length of db_name */
char *table_name; /* Name of the table 'table' */
uint table_name_len; /* Name of table_name */
LEX_STRING *db_name; /* Name of the database containing 'table' */
LEX_STRING *table_name; /* Name of the table 'table' */
void store_record_for_update()
{
store_record(stat_table, record[1]);
}
void store_record_for_lookup()
{
store_record(stat_table, record[0]);
}
bool update_record()
{
int err;
if ((err= stat_file->ha_update_row(record[1], record[0])) &&
err != HA_ERR_RECORD_IS_THE_SAME)
return TRUE;
return FALSE;
}
public:
/*
/**
@details
This constructor has to be called by any constructor of the derived
classes. The constructor 'tunes' the private and protected members of
......@@ -278,24 +361,54 @@ class Stat_table
statistical data of our interest and to the table 'tab' for which this
statistics has been collected.
*/
Stat_table(TABLE *stat, TABLE *tab) :stat_table(stat), table(tab)
{
stat_file= stat_table->file;
/* Currently any statistical table has only one key */
stat_key_idx= 0;
stat_key_info= &stat_table->key_info[stat_key_idx];
stat_key_length= stat_key_info->key_length;
record[0]= stat_table->record[0];
record[1]= stat_table->record[1];
db_name= table->s->db.str;
db_name_len= table->s->db.length;
table_name= table->s->table_name.str;
table_name_len= table->s->table_name.length;
common_init_stat_table();
db_name= &table->s->db;
table_name= &table->s->table_name;
}
/**
@details
This constructor has to be called by any constructor of the derived
classes. The constructor 'tunes' the private and protected members of
the constructed object to the statistical table 'stat_table' with the
statistical data of our interest and to the table t for which this
statistics has been collected. The table t is uniquely specified
by the database name 'db' and the table name 'tab'.
*/
Stat_table(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
:stat_table(stat), table(NULL)
{
common_init_stat_table();
db_name= db;
table_name= tab;
}
virtual ~Stat_table() {}
/*
/**
@brief
Store the given values of fields for database name and table name
@details
This is a purely virtual method.
The implementation for any derived class shall store the given
values of the database name and table name in the corresponding
fields of stat_table.
@note
The method is called by the update_table_name_key_parts function.
*/
virtual void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)= 0;
/**
@brief
Store statistical data into fields of the statistical table
......@@ -307,9 +420,11 @@ class Stat_table
@note
The method is called by the update_stat function.
*/
virtual void store_stat_fields()= 0;
/*
/**
@brief
Read statistical data from fields of the statistical table
......@@ -318,11 +433,13 @@ class Stat_table
The implementation for any derived read shall read the appropriate
statistical data from the corresponding fields of stat_table.
*/
virtual void get_stat_values()= 0;
/*
@breif
Find a record by key in the statistical table
/**
@brief
Find a record in the statistical table by a primary key
@details
The function looks for a record in stat_table by its primary key.
......@@ -334,6 +451,7 @@ class Stat_table
@retval
TRUE the record is found
*/
bool find_stat()
{
uchar key[MAX_KEY_LENGTH];
......@@ -342,8 +460,38 @@ class Stat_table
HA_WHOLE_KEY, HA_READ_KEY_EXACT);
}
/*
@breif
/**
@brief
Find a record in the statistical table by a key prefix value
@details
The function looks for a record in stat_table by the key value consisting
of 'prefix_parts' major components for the primary index.
It assumes that the key prefix fields have been already stored in the record
buffer of stat_table.
@retval
FALSE the record is not found
@retval
TRUE the record is found
*/
bool find_next_stat_for_prefix(uint prefix_parts)
{
uchar key[MAX_KEY_LENGTH];
uint prefix_key_length= 0;
for (uint i= 0; i < prefix_parts; i++)
prefix_key_length+= stat_key_info->key_part[i].store_length;
key_copy(key, record[0], stat_key_info, prefix_key_length);
key_part_map prefix_map= (key_part_map) ((1 << prefix_parts) - 1);
return !stat_file->ha_index_read_idx_map(record[0], stat_key_idx, key,
prefix_map, HA_READ_KEY_EXACT);
}
/**
@brief
Update/insert a record in the statistical table with new statistics
@details
......@@ -365,58 +513,141 @@ class Stat_table
The function calls the virtual method store_stat_fields to populate the
statistical fields of the updated/inserted row with new statistics.
*/
bool update_stat()
{
int err;
if (find_stat())
{
store_record(stat_table, record[1]);
store_record_for_update();
store_stat_fields();
if ((err= stat_file->ha_update_row(record[1], record[0])) &&
err != HA_ERR_RECORD_IS_THE_SAME)
return TRUE;
return update_record();
}
else
{
int err;
store_stat_fields();
if ((err= stat_file->ha_write_row(record[0])))
return TRUE;
}
return FALSE;
}
/**
@brief
Update the table name fields in the current record of stat_table
@details
The function updates the fields containing database name and table name
for the last found record in the statistical table stat_table.
The corresponding names for update is taken from the parameters
db and tab.
@retval
FALSE success with the update of the record
@retval
TRUE failure with the update of the record
@note
The function calls the virtual method change_full_table_name
to store the new names in the record buffer used for updates.
*/
bool update_table_name_key_parts(LEX_STRING *db, LEX_STRING *tab)
{
store_record_for_update();
change_full_table_name(db, tab);
bool rc= update_record();
store_record_for_lookup();
return rc;
}
/**
@brief
Delete the current record of the statistical table stat_table
@details
The function deletes the last found record from the statistical
table stat_table.
@retval
FALSE success with the deletion of the record
@retval
TRUE failure with the deletion of the record
*/
bool delete_stat()
{
int err;
if ((err= stat_file->ha_delete_row(record[0])))
return TRUE;
return FALSE;
}
};
/*
An object of the class Table_stat is created to read statistical
data on tables from the statistical table table_stat or to update
table_stat with such statistical data.
data on tables from the statistical table table_stat, to update
table_stat with such statistical data, or to update columns
of the primary key, or to delete the record by its primary key or
its prefix.
Rows from the statistical table are read and updated always by
primary key.
*/
class Table_stat: public Stat_table
{
private:
Field *db_name_field; /* Field for the column table_stat.db_name */
Field *table_name_field; /* Field for the column table_stat.table_name */
void common_init_table_stat()
{
db_name_field= stat_table->field[TABLE_STAT_DB_NAME];
table_name_field= stat_table->field[TABLE_STAT_TABLE_NAME];
}
void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
}
public:
/*
/**
@details
The constructor 'tunes' the private and protected members of the
constructed object for the statistical table table_stat to read/update
statistics on table 'tab'. The TABLE structure for the table table_stat
must be passed as a value for the parameter 'stat'.
*/
Table_stat(TABLE *stat, TABLE *tab) :Stat_table(stat, tab)
{
db_name_field= stat_table->field[TABLE_STAT_DB_NAME];
table_name_field= stat_table->field[TABLE_STAT_TABLE_NAME];
common_init_table_stat();
}
/*
/**
@details
The constructor 'tunes' the private and protected members of the
object constructed for the statistical table table_stat for
the future updates/deletes of the record concerning the table 'tab'
from the database 'db'.
*/
Table_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
:Stat_table(stat, db, tab)
{
common_init_table_stat();
}
/**
@brief
Set the key fields for the statistical table table_stat
......@@ -429,13 +660,16 @@ class Table_stat: public Stat_table
The function is supposed to be called before any use of the
method find_stat for an object of the Table_stat class.
*/
void set_key_fields()
{
db_name_field->store(db_name, db_name_len, &my_charset_bin);
table_name_field->store(table_name, table_name_len, &my_charset_bin);
db_name_field->store(db_name->str, db_name->length, system_charset_info);
table_name_field->store(table_name->str, table_name->length,
system_charset_info);
}
/*
/**
@brief
Store statistical data into statistical fields of table_stat
......@@ -445,6 +679,7 @@ class Table_stat: public Stat_table
the value of the flag write_stat.cardinality_is_null and the value of
the field write_stat.cardinality' from the TABLE structure for 'table'.
*/
void store_stat_fields()
{
Field *stat_field= stat_table->field[TABLE_STAT_CARDINALITY];
......@@ -457,7 +692,8 @@ class Table_stat: public Stat_table
}
}
/*
/**
@brief
Read statistical data from statistical fields of table_stat
......@@ -470,6 +706,7 @@ class Table_stat: public Stat_table
and the value of the field read_stat.cardinality' from the TABLE structure
for 'table' accordingly.
*/
void get_stat_values()
{
table->read_stat.cardinality_is_null= TRUE;
......@@ -490,63 +727,140 @@ class Table_stat: public Stat_table
/*
An object of the class Column_stat is created to read statistical data
on table columns from the statistical table column_stat or to update
column_stat with such statistical data.
on table columns from the statistical table column_stat, to update
column_stat with such statistical data, or to update columns
of the primary key, or to delete the record by its primary key or
its prefix.
Rows from the statistical table are read and updated always by
primary key.
*/
class Column_stat: public Stat_table
{
private:
Field *db_name_field; /* Field for the column column_stat.db_name */
Field *table_name_field; /* Field for the column column_stat.table_name */
Field *column_name_field; /* Field for the column column_stat.column_name */
Field *table_field; /* Field from 'table' to read /update statistics on */
void common_init_column_stat_table()
{
db_name_field= stat_table->field[COLUMN_STAT_DB_NAME];
table_name_field= stat_table->field[COLUMN_STAT_TABLE_NAME];
column_name_field= stat_table->field[COLUMN_STAT_COLUMN_NAME];
}
void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
}
public:
/*
/**
@details
The constructor 'tunes' the private and protected members of the
constructed object for the statistical table column_stat to read/update
statistics on fields of the table 'tab'. The TABLE structure for the table
column_stat must be passed as a value for the parameter 'stat'.
*/
Column_stat(TABLE *stat, TABLE *tab) :Stat_table(stat, tab)
{
db_name_field= stat_table->field[COLUMN_STAT_DB_NAME];
table_name_field= stat_table->field[COLUMN_STAT_TABLE_NAME];
column_name_field= stat_table->field[COLUMN_STAT_COLUMN_NAME];
common_init_column_stat_table();
}
/*
/**
@details
The constructor 'tunes' the private and protected members of the
object constructed for the statistical table column_stat for
the future updates/deletes of the record concerning the table 'tab'
from the database 'db'.
*/
Column_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
:Stat_table(stat, db, tab)
{
common_init_column_stat_table();
}
/**
@brief
Set table name fields for the statistical table column_stat
@details
The function stores the values of the fields db_name and table_name
of the statistical table column_stat in the record buffer.
*/
void set_full_table_name()
{
db_name_field->store(db_name->str, db_name->length, system_charset_info);
table_name_field->store(table_name->str, table_name->length,
system_charset_info);
}
/**
@brief
Set the key fields for the statistical table column_stat
@param
column Field for the 'table' column to read/update statistics on
col Field for the 'table' column to read/update statistics on
@details
The function sets the values of the fields db_name, table_name and
The function stores the values of the fields db_name, table_name and
column_name in the record buffer for the statistical table column_stat.
These fields comprise the primary key for the table.
It also sets table_field to the passed parameter.
@note
The function is supposed to be called before any use of the
method find_stat for an object of the Column_stat class.
*/
void set_key_fields(Field *column)
void set_key_fields(Field *col)
{
db_name_field->store(db_name, db_name_len, &my_charset_bin);
table_name_field->store(table_name, table_name_len, &my_charset_bin);
table_field= column;
const char *column_name= column->field_name;
column_name_field->store(column_name, strlen(column_name), &my_charset_bin);
set_full_table_name();
const char *column_name= col->field_name;
column_name_field->store(column_name, strlen(column_name),
system_charset_info);
table_field= col;
}
/*
/**
@brief
Update the table name fields in the current record of stat_table
@details
The function updates the primary key fields containing database name,
table name, and column name for the last found record in the statistical
table column_stat.
@retval
FALSE success with the update of the record
@retval
TRUE failure with the update of the record
*/
bool update_column_key_part(const char *col)
{
store_record_for_update();
set_full_table_name();
column_name_field->store(col, strlen(col), system_charset_info);
bool rc= update_record();
store_record_for_lookup();
return rc;
}
/**
@brief
Store statistical data into statistical fields of column_stat
......@@ -567,6 +881,7 @@ class Column_stat: public Stat_table
is less than the length of the string the string is trimmed to fit the
length of the column.
*/
void store_stat_fields()
{
char buff[MAX_FIELD_WIDTH];
......@@ -613,7 +928,8 @@ class Column_stat: public Stat_table
}
}
/*
/**
@brief
Read statistical data from statistical fields of column_stat
......@@ -628,6 +944,7 @@ class Column_stat: public Stat_table
max_value, nulls_ratio, avg_length and avg_frequency of the structure
read_stat from the Field structure for the field 'table_field'.
*/
void get_stat_values()
{
set_nulls_for_read_column_stat_values(table_field);
......@@ -684,15 +1001,19 @@ class Column_stat: public Stat_table
/*
An object of the class Index_stat is created to read statistical
data on index prefixes from the statistical table index_stat or
to update index_stat with such statistical data.
data on tables from the statistical table table_stat, to update
index_stat with such statistical data, or to update columns
of the primary key, or to delete the record by its primary key or
its prefix.
Rows from the statistical table are read and updated always by
primary key.
*/
class Index_stat: public Stat_table
{
private:
Field *db_name_field; /* Field for the column index_stat.db_name */
Field *table_name_field; /* Field for the column index_stat.table_name */
Field *index_name_field; /* Field for the column index_stat.table_name */
......@@ -701,9 +1022,24 @@ class Index_stat: public Stat_table
KEY *table_key_info; /* Info on the index to read/update statistics on */
uint prefix_arity; /* Number of components of the index prefix of interest */
void common_init_index_stat_table()
{
db_name_field= stat_table->field[INDEX_STAT_DB_NAME];
table_name_field= stat_table->field[INDEX_STAT_TABLE_NAME];
index_name_field= stat_table->field[INDEX_STAT_INDEX_NAME];
prefix_arity_field= stat_table->field[INDEX_STAT_PREFIX_ARITY];
}
void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
}
public:
/*
/**
@details
The constructor 'tunes' the private and protected members of the
constructed object for the statistical table index_stat to read/update
......@@ -713,14 +1049,69 @@ class Index_stat: public Stat_table
*/
Index_stat(TABLE *stat, TABLE *tab) :Stat_table(stat, tab)
{
db_name_field= stat_table->field[INDEX_STAT_DB_NAME];
table_name_field= stat_table->field[INDEX_STAT_TABLE_NAME];
index_name_field= stat_table->field[INDEX_STAT_INDEX_NAME];
prefix_arity_field= stat_table->field[INDEX_STAT_PREFIX_ARITY];
common_init_index_stat_table();
}
/*
/**
@details
The constructor 'tunes' the private and protected members of the
object constructed for the statistical table index_stat for
the future updates/deletes of the record concerning the table 'tab'
from the database 'db'.
*/
Index_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
:Stat_table(stat, db, tab)
{
common_init_index_stat_table();
}
/**
@brief
Set table name fields for the statistical table index_stat
@details
The function stores the values of the fields db_name and table_name
of the statistical table index_stat in the record buffer.
*/
void set_full_table_name()
{
db_name_field->store(db_name->str, db_name->length, system_charset_info);
table_name_field->store(table_name->str, table_name->length,
system_charset_info);
}
/**
@brief
Set the key fields of index_stat used to access records for index prefixes
@param
index_info Info for the index of 'table' to read/update statistics on
@details
The function sets the values of the fields db_name, table_name and
index_name in the record buffer for the statistical table index_stat.
It also sets table_key_info to the passed parameter.
@note
The function is supposed to be called before any use of the method
find_next_stat_for_prefix for an object of the Index_stat class.
*/
void set_index_prefix_key_fields(KEY *index_info)
{
set_full_table_name();
char *index_name= index_info->name;
index_name_field->store(index_name, strlen(index_name),
system_charset_info);
table_key_info= index_info;
}
/**
@brief
Set the key fields for the statistical table index_stat
......@@ -729,7 +1120,6 @@ class Index_stat: public Stat_table
@param
index_prefix_arity Number of components in the index prefix of interest
@details
The function sets the values of the fields db_name, table_name and
index_name, prefix_arity in the record buffer for the statistical
......@@ -739,20 +1129,18 @@ class Index_stat: public Stat_table
The function is supposed to be called before any use of the
method find_stat for an object of the Index_stat class.
*/
void set_key_fields(KEY *index_info, uint index_prefix_arity)
{
db_name_field->store(db_name, db_name_len, &my_charset_bin);
table_name_field->store(table_name, table_name_len, &my_charset_bin);
table_key_info= index_info;
char *index_name= index_info->name;
index_name_field->store(index_name, strlen(index_name), &my_charset_bin);
set_index_prefix_key_fields(index_info);
prefix_arity= index_prefix_arity;
prefix_arity_field->store(index_prefix_arity, TRUE);
}
/*
/**
@brief
Store statistical data into statistical fields of tableindex_stat
Store statistical data into statistical fields of table index_stat
@details
This implementation of a purely virtual method sets the value of the
......@@ -762,6 +1150,7 @@ class Index_stat: public Stat_table
If the value of write_stat. avg_frequency[Index_stat::prefix_arity] is
equal to 0, the value of the column is set to NULL.
*/
void store_stat_fields()
{
Field *stat_field= stat_table->field[INDEX_STAT_AVG_FREQUENCY];
......@@ -776,7 +1165,8 @@ class Index_stat: public Stat_table
}
}
/*
/**
@brief
Read statistical data from statistical fields of index_stat
......@@ -791,6 +1181,7 @@ class Index_stat: public Stat_table
set to 0. Otherwise, read_stat.avg_frequency[Index_stat::prefix_arity] is
set to the value of the column.
*/
void get_stat_values()
{
double avg_frequency= 0;
......@@ -826,12 +1217,12 @@ class Count_distinct_field: public Sql_alloc
public:
/*
/**
@param
field Field for which the number of distinct values is
to be find out
@param
max_heap_table_size The linit for the memory used by the RB tree container
max_heap_table_size The limit for the memory used by the RB tree container
of the constructed Unique object 'tree'
@details
......@@ -840,6 +1231,7 @@ class Count_distinct_field: public Sql_alloc
The type of 'field' and the value max_heap_table_size of determine the set
of the parameters to be passed to the constructor of the Unique object.
*/
Count_distinct_field(Field *field, uint max_heap_table_size)
{
qsort_cmp2 compare_key;
......@@ -874,7 +1266,7 @@ class Count_distinct_field: public Sql_alloc
/*
@brief
Check whether the Unique object tree has been succesfully created
Check whether the Unique object tree has been successfully created
*/
bool exists()
{
......@@ -941,7 +1333,9 @@ class Count_distinct_field_bit: public Count_distinct_field
class Index_prefix_calc: public Sql_alloc
{
private:
/* Table containing index specified by index_info */
TABLE *index_table;
/* Info for the index i for whose prefix 'avg_frequency' is calculated */
......@@ -964,7 +1358,7 @@ class Index_prefix_calc: public Sql_alloc
the last encountered k-component prefix
*/
ulonglong prefix_count;
/* The values of the last encoutered k-component prefix */
/* The values of the last encountered k-component prefix */
Cached_item *last_prefix;
};
......@@ -975,6 +1369,7 @@ class Index_prefix_calc: public Sql_alloc
Prefix_calc_state *calc_state;
public:
Index_prefix_calc(TABLE *table, KEY *key_info)
: index_table(table), index_info(key_info)
{
......@@ -1006,7 +1401,7 @@ class Index_prefix_calc: public Sql_alloc
}
}
/*
/**
@breif
Change the elements of calc_state after reading the next index entry
......@@ -1020,6 +1415,7 @@ class Index_prefix_calc: public Sql_alloc
any of these k components has changed. If so, the value of
calc_state[k-1].prefix_count is incremented by 1.
*/
void add()
{
uint i;
......@@ -1045,7 +1441,7 @@ class Index_prefix_calc: public Sql_alloc
}
}
/*
/**
@brief
Calculate the values of avg_frequency for all prefixes of an index
......@@ -1057,6 +1453,7 @@ class Index_prefix_calc: public Sql_alloc
If calc_state[k-1].prefix_count happens to be 0, the value of
avg_frequency[k-1] is set to 0, i.e. is considered as unknown.
*/
void get_avg_frequency()
{
uint i;
......@@ -1358,25 +1755,34 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
table_field= *field_ptr;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
if (rows)
{
val= (double) table_field->nulls / rows;
table_field->write_stat.set_nulls_ratio(val);
set_not_null_for_write_column_stat_value(table_field,
COLUMN_STAT_NULLS_RATIO);
}
if (rows-table_field->nulls)
{
val= (double) table_field->column_total_length / (rows-table_field->nulls);
table_field->write_stat.set_avg_length(val);
set_not_null_for_write_column_stat_value(table_field,
COLUMN_STAT_AVG_LENGTH);
}
if (table_field->count_distinct)
{
val= (double) (rows-table_field->nulls) /
table_field->count_distinct->get_value();
ulonglong count_distinct= table_field->count_distinct->get_value();
if (count_distinct)
{
val= (double) (rows-table_field->nulls) / count_distinct;
table_field->write_stat.set_avg_frequency(val);
set_not_null_for_write_column_stat_value(table_field,
COLUMN_STAT_AVG_FREQUENCY);
}
delete table_field->count_distinct;
table_field->count_distinct= NULL;
}
set_not_null_for_write_column_stat_value(table_field,
COLUMN_STAT_NULLS_RATIO);
set_not_null_for_write_column_stat_value(table_field,
COLUMN_STAT_AVG_LENGTH);
}
}
......@@ -1409,7 +1815,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
@details
For each statistical table st the function looks for the rows from this
table that contain statistical data on 'table'. If rows with given
statistical characteritics exist they are updated with the new statistical
statistical characteristics exist they are updated with the new statistical
values taken from internal structures for 'table'. Otherwise new rows
with these statistical characteristics are added into st.
It is assumed that values stored in the statistical tables are found and
......@@ -1451,7 +1857,10 @@ int update_statistics_for_table(THD *thd, TABLE *table)
if (unlock_tables_n_open_system_tables_for_write(thd,
tables,
&open_tables_backup))
DBUG_RETURN(1);
{
thd->clear_error();
DBUG_RETURN(rc);
}
/* Update the statistical table table_stat */
stat_table= tables[TABLE_STAT].table;
......@@ -1473,7 +1882,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
restore_record(stat_table, s->default_values);
column_stat.set_key_fields(table_field);
err= column_stat.update_stat();
if (err & !rc)
if (err && !rc)
rc= 1;
}
......@@ -1492,7 +1901,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
restore_record(stat_table, s->default_values);
index_stat.set_key_fields(key_info, i+1);
err= index_stat.update_stat();
if (err & !rc)
if (err && !rc)
rc= 1;
}
}
......@@ -1521,7 +1930,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
The function is called in function open_tables.
@retval
0 If data has been succesfully read from all statistical tables
0 If data has been successfully read from all statistical tables
@retval
1 Otherwise
......@@ -1552,11 +1961,14 @@ int read_statistics_for_table(THD *thd, TABLE *table)
init_mdl_requests(tables);
if (open_system_tables_for_read(thd, tables, &open_tables_backup))
DBUG_RETURN(1);
{
thd->clear_error();
DBUG_RETURN(0);
}
create_min_max_stistical_fields(table, FALSE);
/* Read statistics from the statistical table index_stat */
/* Read statistics from the statistical table table_stat */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, table);
table_stat.set_key_fields();
......@@ -1637,6 +2049,369 @@ int read_statistics_for_table(THD *thd, TABLE *table)
}
/**
@brief
Delete statistics on a table from all statistical tables
@param
thd The thread handle
@param
db The name of the database the table belongs to
@param
tab The name of the table whose statistics is to be deleted
@details
The function delete statistics on the table called 'tab' of the database
'db' from all statistical tables: table_stat, column_stat, index_stat.
@retval
0 If all deletions are successful
@retval
1 Otherwise
@note
The function is called when executing the statement DROP TABLE 'tab'.
*/
int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab)
{
int err;
TABLE *stat_table;
TABLE_LIST tables[STATISTICS_TABLES];
Open_tables_backup open_tables_backup;
int rc= 0;
DBUG_ENTER("delete_statistics_for_table");
init_table_list_for_stat_tables(tables, TRUE);
init_mdl_requests(tables);
if (open_system_tables_for_read(thd,
tables,
&open_tables_backup))
{
thd->clear_error();
DBUG_RETURN(rc);
}
/* Delete statistics on table from the statistical table index_stat */
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
while (index_stat.find_next_stat_for_prefix(2))
{
err= index_stat.delete_stat();
if (err & !rc)
rc= 1;
}
/* Delete statistics on table from the statistical table column_stat */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
while (column_stat.find_next_stat_for_prefix(2))
{
err= column_stat.delete_stat();
if (err & !rc)
rc= 1;
}
/* Delete statistics on table from the statistical table table_stat */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, db, tab);
table_stat.set_key_fields();
if (table_stat.find_stat())
{
err= table_stat.delete_stat();
if (err & !rc)
rc= 1;
}
close_system_tables(thd, &open_tables_backup);
DBUG_RETURN(rc);
}
/**
@brief
Delete statistics on a column of the specified table
@param
thd The thread handle
@param
tab The table the column belongs to
@param
col The field of the column whose statistics is to be deleted
@details
The function delete statistics on the column 'col' belonging to the table
'tab' from the statistical table column_stat.
@retval
0 If the deletion is successful
@retval
1 Otherwise
@note
The function is called when dropping a table column or when changing
the definition of this column.
*/
int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col)
{
int err;
TABLE *stat_table;
TABLE_LIST tables;
Open_tables_backup open_tables_backup;
int rc= 0;
DBUG_ENTER("delete_statistics_for_column");
init_table_list_for_single_stat_table(&tables, &stat_table_name[1], TRUE);
init_mdl_requests(&tables);
if (open_system_tables_for_read(thd,
&tables,
&open_tables_backup))
{
thd->clear_error();
DBUG_RETURN(rc);
}
stat_table= tables.table;
Column_stat column_stat(stat_table, tab);
column_stat.set_key_fields(col);
if (column_stat.find_stat())
{
err= column_stat.delete_stat();
if (err)
rc= 1;
}
close_system_tables(thd, &open_tables_backup);
DBUG_RETURN(rc);
}
/**
@brief
Delete statistics on an index of the specified table
@param
thd The thread handle
@param
tab The table the index belongs to
@param
key_info The descriptor of the index whose statistics is to be deleted
@details
The function delete statistics on the index specified by 'key_info'
defined on the table 'tab' from the statistical table index_stat.
@retval
0 If the deletion is successful
@retval
1 Otherwise
@note
The function is called when dropping an index, or dropping/changing the
definition of a column used in the definition of the index.
*/
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info)
{
int err;
TABLE *stat_table;
TABLE_LIST tables;
Open_tables_backup open_tables_backup;
int rc= 0;
DBUG_ENTER("delete_statistics_for_index");
init_table_list_for_single_stat_table(&tables, &stat_table_name[2], TRUE);
init_mdl_requests(&tables);
if (open_system_tables_for_read(thd,
&tables,
&open_tables_backup))
{
thd->clear_error();
DBUG_RETURN(rc);
}
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))
{
err= index_stat.delete_stat();
if (err && !rc)
rc= 1;
}
close_system_tables(thd, &open_tables_backup);
DBUG_RETURN(rc);
}
/**
@brief
Rename a table in all statistical tables
@param
thd The thread handle
@param
db The name of the database the table belongs to
@param
tab The name of the table to be renamed in statistical tables
@param
new_tab The new name of the table
@details
The function replaces the name of the table 'tab' from the database 'db'
for 'new_tab' in all all statistical tables: table_stat, column_stat,
index_stat.
@retval
0 If all updates of the table name are successful
@retval
1 Otherwise
@note
The function is called when executing any statement that renames a table
*/
int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
LEX_STRING *new_db, LEX_STRING *new_tab)
{
int err;
TABLE *stat_table;
TABLE_LIST tables[STATISTICS_TABLES];
Open_tables_backup open_tables_backup;
int rc= 0;
DBUG_ENTER("rename_table_in_stat_tables");
init_table_list_for_stat_tables(tables, TRUE);
init_mdl_requests(tables);
if (open_system_tables_for_read(thd,
tables,
&open_tables_backup))
{
thd->clear_error();
DBUG_RETURN(rc);
}
/* Rename table in the statistical table index_stat */
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
while (index_stat.find_next_stat_for_prefix(2))
{
err= index_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
index_stat.set_full_table_name();
}
/* Rename table in the statistical table column_stat */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
while (column_stat.find_next_stat_for_prefix(2))
{
err= column_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
column_stat.set_full_table_name();
}
/* Rename table in the statistical table table_stat */
stat_table= tables[TABLE_STAT].table;
Table_stat table_stat(stat_table, db, tab);
table_stat.set_key_fields();
if (table_stat.find_stat())
{
err= table_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
}
close_system_tables(thd, &open_tables_backup);
DBUG_RETURN(rc);
}
/**
@brief
Rename a column in the statistical table column_stat
@param
thd The thread handle
@param
tab The table the column belongs to
@param
col The column to be renamed
@param
new_name The new column name
@details
The function replaces the name of the column 'col' belonging to the table
'tab' for 'new_name' in the statistical table column_stat..
@retval
0 If all updates of the table name are successful
@retval
1 Otherwise
@note
The function is called when executing any statement that renames a column,
but does not change the column definition.
*/
int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
const char *new_name)
{
int err;
TABLE *stat_table;
TABLE_LIST tables;
Open_tables_backup open_tables_backup;
int rc= 0;
DBUG_ENTER("rename_column_in_stat_tables");
init_table_list_for_single_stat_table(&tables, &stat_table_name[1], TRUE);
init_mdl_requests(&tables);
if (open_system_tables_for_read(thd,
&tables,
&open_tables_backup))
{
thd->clear_error();
DBUG_RETURN(rc);
}
/* Rename column in the statistical table table_stat */
stat_table= tables.table;
Column_stat column_stat(stat_table, tab);
column_stat.set_key_fields(col);
if (column_stat.find_stat())
{
err= column_stat.update_column_key_part(new_name);
if (err & !rc)
rc= 1;
}
close_system_tables(thd, &open_tables_backup);
DBUG_RETURN(rc);
}
/**
@brief
Set statistics for a table that will be used by the optimizer
......
......@@ -1878,6 +1878,17 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
}
}
if (!in_bootstrap)
{
for (table= tables; table; table= table->next_local)
{
LEX_STRING db_name= { table->db, table->db_length };
LEX_STRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY || !find_temporary_table(thd, table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
}
}
mysql_ha_rm_tables(thd, tables);
if (!drop_temporary)
......@@ -1888,6 +1899,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
MYSQL_OPEN_SKIP_TEMPORARY))
DBUG_RETURN(true);
for (table= tables; table; table= table->next_local)
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
false);
}
......@@ -5084,6 +5096,21 @@ mysql_compare_tables(TABLE *table,
thd->calloc(sizeof(void*) * table->s->keys)) == NULL)
DBUG_RETURN(1);
tmp_new_field_it.init(tmp_alter_info.create_list);
for (i= 0, f_ptr= table->field, tmp_new_field= tmp_new_field_it++;
(field= *f_ptr);
i++, f_ptr++, tmp_new_field= tmp_new_field_it++)
{
if (field->is_equal(tmp_new_field) == IS_EQUAL_NO &&
table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_column(thd, table, field);
else if (my_strcasecmp(system_charset_info,
field->field_name,
tmp_new_field->field_name))
(void) rename_column_in_stat_tables(thd, table, field,
tmp_new_field->field_name);
}
/*
Use transformed info to evaluate possibility of in-place ALTER TABLE
but use the preserved field to persist modifications.
......@@ -5144,7 +5171,12 @@ mysql_compare_tables(TABLE *table,
if (my_strcasecmp(system_charset_info,
field->field_name,
tmp_new_field->field_name))
{
field->flags|= FIELD_IS_RENAMED;
if (table->s->tmp_table == NO_TMP_TABLE)
rename_column_in_stat_tables(thd, table, field,
tmp_new_field->field_name);
}
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
if (!(tmp= field->is_equal(tmp_new_field)))
......@@ -5247,6 +5279,8 @@ mysql_compare_tables(TABLE *table,
field= table->field[key_part->fieldnr];
field->flags|= FIELD_IN_ADD_INDEX;
}
if (table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_index(thd, table, table_key);
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
}
/*end of for (; table_key < table_key_end;) */
......@@ -5504,6 +5538,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
if (drop)
{
if (table->s->tmp_table == NO_TMP_TABLE)
(void) delete_statistics_for_column(thd, table, field);
drop_it.remove();
/*
ALTER TABLE DROP COLUMN always changes table data even in cases
......@@ -5656,12 +5692,15 @@ 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);
drop_it.remove();
continue;
}
KEY_PART_INFO *key_part= key_info->key_part;
key_parts.empty();
bool delete_index_stat= FALSE;
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
if (!key_part->field)
......@@ -5684,7 +5723,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
break;
}
if (!cfield)
{
delete_index_stat= TRUE;
continue; // Field is removed
}
key_part_length= key_part->length;
if (cfield->field) // Not new field
{
......@@ -5726,6 +5768,8 @@ 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 (key_parts.elements)
{
KEY_CREATE_INFO key_create_info;
......@@ -5905,6 +5949,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
enum ha_extra_function extra_func= thd->locked_tables_mode
? HA_EXTRA_NOT_USED
: HA_EXTRA_FORCE_REOPEN;
LEX_STRING old_db_name= { table_list->db, table_list->db_length };
LEX_STRING old_table_name= { table_list->table_name,
table_list->table_name_length };
DBUG_ENTER("mysql_alter_table");
/*
......@@ -6209,6 +6256,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
LEX_STRING new_db_name= { new_db, strlen(new_db) };
LEX_STRING new_table_name= { new_alias, strlen(new_alias) };
(void) rename_table_in_stat_tables(thd, &old_db_name, &old_table_name,
&new_db_name, &new_table_name);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
error= -1;
else if (Table_triggers_list::change_table_name(thd, db,
......@@ -6920,6 +6973,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table is renamed and the SE is also changed, then an intermediate table
is created and the additional call will not take place.
*/
if (new_name != table_name || new_db != db)
{
LEX_STRING new_db_name= { new_db, strlen(new_db) };
LEX_STRING new_table_name= { new_name, strlen(new_name) };
(void) rename_table_in_stat_tables(thd, &old_db_name, &old_table_name,
&new_db_name, &new_table_name);
}
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
{
DBUG_ASSERT(new_db_type == old_db_type);
......
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