mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-5834: Merge Kakao Defragmentation implementation to MariaDB 10.1
Merge https://github.com/kakao/mariadb-10.0 that contains Facebook's implementation for defragmentation facebook/mysql-5.6@a2d3a74 facebook/mysql-5.6@def96c8 facebook/mysql-5.6@9c67c5d facebook/mysql-5.6@921a81b facebook/mysql-5.6@aa519bd facebook/mysql-5.6@fea7d13 facebook/mysql-5.6@09b29d3 facebook/mysql-5.6@9284abb facebook/mysql-5.6@dbd623d facebook/mysql-5.6@aed55dc facebook/mysql-5.6@aad5c82 This version does not add new SQL-syntax and new handler API function. Instead optimize table is mapped to defragment table if innodb_defragment=ON, by default the feature is off. Contains changes authored by Sunguck Lee (Kakao).
This commit is contained in:
29
mysql-test/suite/innodb/r/innodb_defrag_binlog.result
Normal file
29
mysql-test/suite/innodb/r/innodb_defrag_binlog.result
Normal file
@ -0,0 +1,29 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
drop table if exists t1;
|
||||
create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb;
|
||||
insert into t1 values (1, REPEAT("a", 256));
|
||||
insert into t1 values (2, REPEAT("a", 256));
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
drop table t1;
|
||||
show binlog events in 'master-bin.000001' from 313;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 313 Gtid 1 351 GTID 0-1-1
|
||||
master-bin.000001 351 Query 1 465 use `test`; DROP TABLE IF EXISTS `t1`
|
||||
master-bin.000001 465 Gtid 1 503 GTID 0-1-2
|
||||
master-bin.000001 503 Query 1 669 use `test`; create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb
|
||||
master-bin.000001 669 Gtid 1 707 BEGIN GTID 0-1-3
|
||||
master-bin.000001 707 Table_map 1 751 table_id: 82 (test.t1)
|
||||
master-bin.000001 751 Write_rows_v1 1 1043 table_id: 82 flags: STMT_END_F
|
||||
master-bin.000001 1043 Xid 1 1070 COMMIT
|
||||
master-bin.000001 1070 Gtid 1 1108 BEGIN GTID 0-1-4
|
||||
master-bin.000001 1108 Table_map 1 1152 table_id: 82 (test.t1)
|
||||
master-bin.000001 1152 Write_rows_v1 1 1444 table_id: 82 flags: STMT_END_F
|
||||
master-bin.000001 1444 Xid 1 1471 COMMIT
|
||||
master-bin.000001 1471 Gtid 1 1509 GTID 0-1-5
|
||||
master-bin.000001 1509 Query 1 1589 use `test`; optimize table t1
|
||||
master-bin.000001 1589 Gtid 1 1627 GTID 0-1-6
|
||||
master-bin.000001 1627 Query 1 1731 use `test`; DROP TABLE `t1`
|
||||
include/rpl_end.inc
|
73
mysql-test/suite/innodb/r/innodb_defrag_concurrent.result
Normal file
73
mysql-test/suite/innodb/r/innodb_defrag_concurrent.result
Normal file
@ -0,0 +1,73 @@
|
||||
DROP TABLE if exists t1;
|
||||
select @@global.innodb_stats_persistent;
|
||||
@@global.innodb_stats_persistent
|
||||
0
|
||||
set global innodb_defragment_stats_accuracy = 80;
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c INT, KEY second(a, b),KEY third(c)) ENGINE=INNODB;
|
||||
SET @@global.innodb_defragment_n_pages = 20;
|
||||
after populate PRIMARY
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
20000
|
||||
after populate second
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
20000
|
||||
after populate third
|
||||
select count(*) from t1 force index (third);
|
||||
count(*)
|
||||
20000
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
15800
|
||||
after delete PRIMAY
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
15800
|
||||
after delete second
|
||||
select count(*) from t1 force index (third);
|
||||
count(*)
|
||||
15800
|
||||
after delete third
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
optimize table t1;;
|
||||
INSERT INTO t1 VALUES (400000, REPEAT('A', 256),300000);;
|
||||
INSERT INTO t1 VALUES (500000, REPEAT('A', 256),400000);;
|
||||
DELETE FROM t1 where a between 1 and 100;;
|
||||
UPDATE t1 SET c = c + 1 where c between 2000 and 8000;;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
select sleep(5);
|
||||
sleep(5)
|
||||
0
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
15723
|
||||
after optimize PRIMARY
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
15723
|
||||
after optimize second
|
||||
select count(*) from t1 force index (third);
|
||||
count(*)
|
||||
15723
|
||||
after optimize third
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
drop table t1;
|
94
mysql-test/suite/innodb/r/innodb_defrag_stats.result
Normal file
94
mysql-test/suite/innodb/r/innodb_defrag_stats.result
Normal file
@ -0,0 +1,94 @@
|
||||
DROP TABLE if exists t1;
|
||||
select @@global.innodb_stats_persistent;
|
||||
@@global.innodb_stats_persistent
|
||||
0
|
||||
set global innodb_defragment_stats_accuracy = 20;
|
||||
# Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
# Populate data
|
||||
INSERT INTO t1 VALUES(1, REPEAT('A', 256));
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
# Not enough page splits to trigger persistent stats write yet.
|
||||
select count(*) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
count(*)
|
||||
0
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
# Persistent stats recorded.
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
# Delete some rows.
|
||||
delete from t1 where a between 100 * 20 and 100 * 20 + 30;
|
||||
delete from t1 where a between 100 * 19 and 100 * 19 + 30;
|
||||
delete from t1 where a between 100 * 18 and 100 * 18 + 30;
|
||||
delete from t1 where a between 100 * 17 and 100 * 17 + 30;
|
||||
delete from t1 where a between 100 * 16 and 100 * 16 + 30;
|
||||
delete from t1 where a between 100 * 15 and 100 * 15 + 30;
|
||||
delete from t1 where a between 100 * 14 and 100 * 14 + 30;
|
||||
delete from t1 where a between 100 * 13 and 100 * 13 + 30;
|
||||
delete from t1 where a between 100 * 12 and 100 * 12 + 30;
|
||||
delete from t1 where a between 100 * 11 and 100 * 11 + 30;
|
||||
delete from t1 where a between 100 * 10 and 100 * 10 + 30;
|
||||
delete from t1 where a between 100 * 9 and 100 * 9 + 30;
|
||||
delete from t1 where a between 100 * 8 and 100 * 8 + 30;
|
||||
delete from t1 where a between 100 * 7 and 100 * 7 + 30;
|
||||
delete from t1 where a between 100 * 6 and 100 * 6 + 30;
|
||||
delete from t1 where a between 100 * 5 and 100 * 5 + 30;
|
||||
delete from t1 where a between 100 * 4 and 100 * 4 + 30;
|
||||
delete from t1 where a between 100 * 3 and 100 * 3 + 30;
|
||||
delete from t1 where a between 100 * 2 and 100 * 2 + 30;
|
||||
delete from t1 where a between 100 * 1 and 100 * 1 + 30;
|
||||
# Server Restarted
|
||||
# Confirm persistent stats still there after restart.
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
# n_page_split should be 0 after defragmentation, n_pages_freed should be non-zero.
|
||||
select stat_value = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
stat_value = 0
|
||||
1
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
set global innodb_defragment_stats_accuracy = 40;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
# Not enough operation to trigger persistent stats write
|
||||
select stat_value = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
stat_value = 0
|
||||
1
|
||||
1
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
# Persistent stats write triggered
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
stat_value > 0
|
||||
0
|
||||
0
|
||||
# Table rename should cause stats rename.
|
||||
rename table t1 to t2;
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
# Drop index should cause stats drop.
|
||||
drop index SECOND on t2;
|
||||
select count(*) from mysql.innodb_index_stats where table_name like '%t2%' and index_name = 'SECOND';
|
||||
count(*)
|
||||
4
|
||||
Server Restarted
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
# Clean up
|
||||
DROP TABLE t2;
|
@ -0,0 +1,36 @@
|
||||
DROP TABLE if exists t1;
|
||||
SET @start_table_definition_cache = @@global.table_definition_cache;
|
||||
SET @@global.table_definition_cache = 400;
|
||||
SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy;
|
||||
SET @@global.innodb_defragment_stats_accuracy = 10;
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES(1, REPEAT('A', 256));
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
stat_value > 0
|
||||
Create 405 table to overflow the table cache.
|
||||
Sleep for a while to make sure t1 is evicted.
|
||||
select sleep(10);
|
||||
sleep(10)
|
||||
0
|
||||
Reload t1 to get defrag stats from persistent storage
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
make sure the stats thread will wake up and do the write even if there's a race condition between set and reset.
|
||||
select sleep(12);
|
||||
sleep(12)
|
||||
0
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
stat_value > 0
|
||||
SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy;
|
||||
SET @@global.table_definition_cache = @start_table_definition_cache;
|
||||
DROP TABLE t1;
|
81
mysql-test/suite/innodb/r/innodb_defragment.result
Normal file
81
mysql-test/suite/innodb/r/innodb_defragment.result
Normal file
@ -0,0 +1,81 @@
|
||||
DROP TABLE if exists t1;
|
||||
set global innodb_defragment_stats_accuracy = 80;
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
INSERT INTO t1 VALUES (100000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (200000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (300000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (400000, REPEAT('A', 256));
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
create procedure defragment()
|
||||
begin
|
||||
set @i = 0;
|
||||
repeat
|
||||
set @i = @i + 1;
|
||||
optimize table t1;
|
||||
select sleep(5);
|
||||
until @i = 3 end repeat;
|
||||
end //
|
||||
select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
count(stat_value) = 0
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
1
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
10004
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
10004
|
||||
call defragment();
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
select sleep(5);
|
||||
sleep(5)
|
||||
0
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
7904
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
7904
|
||||
SET @@global.innodb_defragment_n_pages = 3;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
6904
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
6904
|
||||
SET @@global.innodb_defragment_n_pages = 10;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
count(stat_value) > 0
|
||||
0
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
6904
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
6904
|
||||
DROP PROCEDURE defragment;
|
||||
DROP TABLE t1;
|
@ -0,0 +1,59 @@
|
||||
DROP TABLE if exists t1;
|
||||
DROP TABLE if exists t2;
|
||||
Testing tables with large records
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
optimize table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
790
|
||||
select count(*) from t1 force index (second);
|
||||
count(*)
|
||||
790
|
||||
# A few more insertions on the page should not cause a page split.
|
||||
insert into t1 values (81, REPEAT('A', 256));
|
||||
insert into t1 values (83, REPEAT('A', 256));
|
||||
insert into t1 values (87, REPEAT('A', 256));
|
||||
insert into t1 values (82, REPEAT('A', 256));
|
||||
insert into t1 values (86, REPEAT('A', 256));
|
||||
# More insertions will cause page splits
|
||||
insert into t1 values (88, REPEAT('A', 50));
|
||||
Too much space are reserved on primary index.
|
||||
Too much space are reserved on second index.
|
||||
DROP TABLE t1;
|
||||
Testing table with small records
|
||||
CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARchar(16), KEY SECOND(a,b)) ENGINE=INNODB;
|
||||
optimize table t2;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t2 optimize status OK
|
||||
select count(*) from t2 force index(second);
|
||||
count(*)
|
||||
3701
|
||||
The page should have room for about 20 insertions
|
||||
insert into t2 values(1181, REPEAT('A', 16));
|
||||
insert into t2 values(1191, REPEAT('A', 16));
|
||||
insert into t2 values(1182, REPEAT('A', 16));
|
||||
insert into t2 values(1192, REPEAT('A', 16));
|
||||
insert into t2 values(1183, REPEAT('A', 16));
|
||||
insert into t2 values(1193, REPEAT('A', 16));
|
||||
insert into t2 values(1184, REPEAT('A', 16));
|
||||
insert into t2 values(1194, REPEAT('A', 16));
|
||||
insert into t2 values(1185, REPEAT('A', 16));
|
||||
insert into t2 values(1195, REPEAT('A', 16));
|
||||
insert into t2 values(1186, REPEAT('A', 16));
|
||||
insert into t2 values(1196, REPEAT('A', 16));
|
||||
insert into t2 values(1187, REPEAT('A', 16));
|
||||
insert into t2 values(1197, REPEAT('A', 16));
|
||||
insert into t2 values(1188, REPEAT('A', 16));
|
||||
insert into t2 values(1198, REPEAT('A', 16));
|
||||
insert into t2 values(1189, REPEAT('A', 16));
|
||||
insert into t2 values(1199, REPEAT('A', 16));
|
||||
insert into t2 values(1190, REPEAT('A', 16));
|
||||
insert into t2 values(1180, REPEAT('A', 16));
|
||||
More insertions will cause page split.
|
||||
insert into t2 values(1280, REPEAT('A', 16));
|
||||
insert into t2 values(1290, REPEAT('A', 16));
|
||||
insert into t2 values(1281, REPEAT('A', 16));
|
||||
insert into t2 values(1291, REPEAT('A', 16));
|
||||
DROP TABLE t2;
|
1
mysql-test/suite/innodb/t/innodb.opt
Normal file
1
mysql-test/suite/innodb/t/innodb.opt
Normal file
@ -0,0 +1 @@
|
||||
--innodb-defragment=0
|
5
mysql-test/suite/innodb/t/innodb_defrag_binlog.opt
Normal file
5
mysql-test/suite/innodb/t/innodb_defrag_binlog.opt
Normal file
@ -0,0 +1,5 @@
|
||||
--loose-innodb-buffer-pool-stats
|
||||
--loose-innodb-buffer-page
|
||||
--loose-innodb-buffer-page-lru
|
||||
--binlog-format=row
|
||||
--innodb-defragment=1
|
19
mysql-test/suite/innodb/t/innodb_defrag_binlog.test
Normal file
19
mysql-test/suite/innodb/t/innodb_defrag_binlog.test
Normal file
@ -0,0 +1,19 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb;
|
||||
|
||||
insert into t1 values (1, REPEAT("a", 256));
|
||||
insert into t1 values (2, REPEAT("a", 256));
|
||||
optimize table t1;
|
||||
|
||||
drop table t1;
|
||||
|
||||
--replace_regex /\/\*.*//
|
||||
show binlog events in 'master-bin.000001' from 313;
|
||||
|
||||
--source include/rpl_end.inc
|
4
mysql-test/suite/innodb/t/innodb_defrag_concurrent.opt
Normal file
4
mysql-test/suite/innodb/t/innodb_defrag_concurrent.opt
Normal file
@ -0,0 +1,4 @@
|
||||
--loose-innodb-buffer-pool-stats
|
||||
--loose-innodb-buffer-page
|
||||
--loose-innodb-buffer-page-lru
|
||||
--innodb-defragment=1
|
180
mysql-test/suite/innodb/t/innodb_defrag_concurrent.test
Normal file
180
mysql-test/suite/innodb/t/innodb_defrag_concurrent.test
Normal file
@ -0,0 +1,180 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
--disable_query_log
|
||||
let $innodb_defragment_n_pages_orig=`select @@innodb_defragment_n_pages`;
|
||||
let $innodb_defragment_stats_accuracy_orig=`select @@innodb_defragment_stats_accuracy`;
|
||||
--enable_query_log
|
||||
|
||||
select @@global.innodb_stats_persistent;
|
||||
set global innodb_defragment_stats_accuracy = 80;
|
||||
|
||||
# Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c INT, KEY second(a, b),KEY third(c)) ENGINE=INNODB;
|
||||
|
||||
connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||
connect (con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||
connect (con3,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||
connect (con4,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||
|
||||
connection default;
|
||||
|
||||
SET @@global.innodb_defragment_n_pages = 20;
|
||||
|
||||
let $data_size = 20000;
|
||||
let $delete_size = 2000;
|
||||
|
||||
# Populate table.
|
||||
let $i = $data_size;
|
||||
--disable_query_log
|
||||
while ($i)
|
||||
{
|
||||
eval
|
||||
INSERT INTO t1 VALUES ($data_size + 1 - $i, REPEAT('A', 256), $i);
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--echo after populate PRIMARY
|
||||
select count(*) from t1;
|
||||
|
||||
if (`select count(*) < 30 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
aelect count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
--echo after populate second
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
if (`select count(*) < 320 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
--ECHO after populate third
|
||||
select count(*) from t1 force index (third);
|
||||
|
||||
if (`select count(*) < 20 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;
|
||||
}
|
||||
|
||||
# Delete some data
|
||||
--disable_query_log
|
||||
let $size = $delete_size;
|
||||
while ($size)
|
||||
{
|
||||
let $j = 100 * $size;
|
||||
eval delete from t1 where a between $j - 20 and $j;
|
||||
dec $size;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
select count(*) from t1;
|
||||
|
||||
--echo after delete PRIMAY
|
||||
if (`select count(*) < 30 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
--echo after delete second
|
||||
if (`select count(*) < 300 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (third);
|
||||
|
||||
--echo after delete third
|
||||
if (`select count(*) > 20 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;
|
||||
}
|
||||
|
||||
# Above delete will free some pages and insert causes page split and these could cause defrag
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
|
||||
connection con1;
|
||||
--send optimize table t1;
|
||||
|
||||
connection default;
|
||||
--send INSERT INTO t1 VALUES (400000, REPEAT('A', 256),300000);
|
||||
|
||||
connection con2;
|
||||
--send INSERT INTO t1 VALUES (500000, REPEAT('A', 256),400000);
|
||||
|
||||
connection con3;
|
||||
--send DELETE FROM t1 where a between 1 and 100;
|
||||
|
||||
connection con4;
|
||||
--send UPDATE t1 SET c = c + 1 where c between 2000 and 8000;
|
||||
|
||||
connection con1;
|
||||
--disable_result_log
|
||||
--reap
|
||||
--enable_result_log
|
||||
|
||||
connection con2;
|
||||
--reap
|
||||
|
||||
connection con3;
|
||||
--reap
|
||||
|
||||
connection con4;
|
||||
--reap
|
||||
|
||||
connection default;
|
||||
--reap
|
||||
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
disconnect con3;
|
||||
disconnect con4;
|
||||
|
||||
optimize table t1;
|
||||
select sleep(5);
|
||||
|
||||
select count(*) from t1;
|
||||
|
||||
--echo after optimize PRIMARY
|
||||
if (`select count(*) > 62 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
--echo after optimize second
|
||||
if (`select count(*) > 340 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (third);
|
||||
|
||||
--echo after optimize third
|
||||
if (`select count(*) > 25 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'third' order by page_number;
|
||||
}
|
||||
|
||||
# Now pages are freed
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
|
||||
drop table t1;
|
||||
|
||||
# reset system
|
||||
--disable_query_log
|
||||
EVAL SET GLOBAL innodb_defragment_n_pages = $innodb_defragment_n_pages_orig;
|
||||
EVAL SET GLOBAL innodb_defragment_stats_accuracy = $innodb_defragment_stats_accuracy_orig;
|
||||
--enable_query_log
|
1
mysql-test/suite/innodb/t/innodb_defrag_stats.opt
Normal file
1
mysql-test/suite/innodb/t/innodb_defrag_stats.opt
Normal file
@ -0,0 +1 @@
|
||||
--innodb-defragment=1
|
87
mysql-test/suite/innodb/t/innodb_defrag_stats.test
Normal file
87
mysql-test/suite/innodb/t/innodb_defrag_stats.test
Normal file
@ -0,0 +1,87 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/big_test.inc
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
--disable_query_log
|
||||
let $innodb_defragment_stats_accuracy_orig=`select @@innodb_defragment_stats_accuracy`;
|
||||
--enable_query_log
|
||||
|
||||
select @@global.innodb_stats_persistent;
|
||||
set global innodb_defragment_stats_accuracy = 20;
|
||||
|
||||
--echo # Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
|
||||
--echo # Populate data
|
||||
INSERT INTO t1 VALUES(1, REPEAT('A', 256));
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
|
||||
--echo # Not enough page splits to trigger persistent stats write yet.
|
||||
select count(*) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
|
||||
--echo # Persistent stats recorded.
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
--echo # Delete some rows.
|
||||
let $num_delete = 20;
|
||||
while ($num_delete)
|
||||
{
|
||||
let $j = 100 * $num_delete;
|
||||
eval delete from t1 where a between $j and $j + 30;
|
||||
dec $num_delete;
|
||||
}
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
--echo # Server Restarted
|
||||
|
||||
--echo # Confirm persistent stats still there after restart.
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
optimize table t1;
|
||||
--echo # n_page_split should be 0 after defragmentation, n_pages_freed should be non-zero.
|
||||
select stat_value = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed', 'n_leaf_pages_defrag');
|
||||
|
||||
set global innodb_defragment_stats_accuracy = 40;
|
||||
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
--echo # Not enough operation to trigger persistent stats write
|
||||
select stat_value = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
--echo # Persistent stats write triggered
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
|
||||
--echo # Table rename should cause stats rename.
|
||||
rename table t1 to t2;
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
--echo # Drop index should cause stats drop.
|
||||
drop index SECOND on t2;
|
||||
select count(*) from mysql.innodb_index_stats where table_name like '%t2%' and index_name = 'SECOND';
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
--echo Server Restarted
|
||||
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
--echo # Clean up
|
||||
DROP TABLE t2;
|
||||
|
||||
--disable_query_log
|
||||
EVAL SET GLOBAL innodb_defragment_stats_accuracy = $innodb_defragment_stats_accuracy_orig;
|
||||
--enable_query_log
|
@ -0,0 +1 @@
|
||||
--innodb-defragment=1
|
@ -0,0 +1,71 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/big_test.inc
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
let $num_tables = 405;
|
||||
|
||||
SET @start_table_definition_cache = @@global.table_definition_cache;
|
||||
SET @@global.table_definition_cache = 400;
|
||||
|
||||
# set stats accuracy to be pretty high so stats sync is easily triggered.
|
||||
SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy;
|
||||
SET @@global.innodb_defragment_stats_accuracy = 10;
|
||||
|
||||
# Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
|
||||
# Populate data
|
||||
INSERT INTO t1 VALUES(1, REPEAT('A', 256));
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
|
||||
# Create many tables to over flow the table definition cache
|
||||
|
||||
--echo Create $num_tables table to overflow the table cache.
|
||||
--disable_query_log
|
||||
let $count = $num_tables;
|
||||
while ($count)
|
||||
{
|
||||
EVAL CREATE TABLE t_$count (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=INNODB;
|
||||
EVAL INSERT INTO t_$count VALUES (1), (2);
|
||||
dec $count;
|
||||
}
|
||||
--enable_query_log
|
||||
--echo Sleep for a while to make sure t1 is evicted.
|
||||
select sleep(10);
|
||||
|
||||
--echo Reload t1 to get defrag stats from persistent storage
|
||||
INSERT INTO t1 (b) SELECT b from t1;
|
||||
|
||||
--echo make sure the stats thread will wake up and do the write even if there's a race condition between set and reset.
|
||||
select sleep(12);
|
||||
|
||||
select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split';
|
||||
|
||||
|
||||
# Clean up
|
||||
SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy;
|
||||
SET @@global.table_definition_cache = @start_table_definition_cache;
|
||||
--disable_query_log
|
||||
let $count = $num_tables;
|
||||
while ($count)
|
||||
{
|
||||
EVAL DROP TABLE t_$count;
|
||||
dec $count;
|
||||
}
|
||||
--enable_query_log
|
||||
DROP TABLE t1;
|
2
mysql-test/suite/innodb/t/innodb_defragment-master.opt
Normal file
2
mysql-test/suite/innodb/t/innodb_defragment-master.opt
Normal file
@ -0,0 +1,2 @@
|
||||
--innodb_file_per_table
|
||||
--innodb-defragment=1
|
4
mysql-test/suite/innodb/t/innodb_defragment.opt
Normal file
4
mysql-test/suite/innodb/t/innodb_defragment.opt
Normal file
@ -0,0 +1,4 @@
|
||||
--loose-innodb-buffer-pool-stats
|
||||
--loose-innodb-buffer-page
|
||||
--loose-innodb-buffer-page-lru
|
||||
--innodb-defragment=1
|
190
mysql-test/suite/innodb/t/innodb_defragment.test
Normal file
190
mysql-test/suite/innodb/t/innodb_defragment.test
Normal file
@ -0,0 +1,190 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
--disable_query_log
|
||||
let $innodb_defragment_n_pages_orig=`select @@innodb_defragment_n_pages`;
|
||||
let $innodb_defragment_stats_accuracy_orig=`select @@innodb_defragment_stats_accuracy`;
|
||||
--enable_query_log
|
||||
|
||||
set global innodb_defragment_stats_accuracy = 80;
|
||||
|
||||
# Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
|
||||
## Test-1 defragment an empty table
|
||||
optimize table t1;
|
||||
|
||||
## Test-2 defragment a single page table
|
||||
INSERT INTO t1 VALUES (100000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (200000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (300000, REPEAT('A', 256));
|
||||
INSERT INTO t1 VALUES (400000, REPEAT('A', 256));
|
||||
|
||||
optimize table t1;
|
||||
|
||||
## Test-3 defragment (somewhat) in parallel with delete queries
|
||||
let $data_size = 10000;
|
||||
let $delete_size = 100;
|
||||
|
||||
delimiter //;
|
||||
create procedure defragment()
|
||||
begin
|
||||
set @i = 0;
|
||||
repeat
|
||||
set @i = @i + 1;
|
||||
optimize table t1;
|
||||
select sleep(5);
|
||||
until @i = 3 end repeat;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
|
||||
# Populate table.
|
||||
let $i = $data_size;
|
||||
--disable_query_log
|
||||
while ($i)
|
||||
{
|
||||
eval
|
||||
INSERT INTO t1 VALUES ($data_size + 1 - $i, REPEAT('A', 256));
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
|
||||
|
||||
select count(*) from t1;
|
||||
|
||||
if (!`select count(*) > 180 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
if (!`select count(*) > 170 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
|
||||
connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||
|
||||
connection con1;
|
||||
--send call defragment()
|
||||
|
||||
connection default;
|
||||
|
||||
--disable_query_log
|
||||
let $size = $delete_size;
|
||||
while ($size)
|
||||
{
|
||||
let $j = 100 * $size;
|
||||
eval delete from t1 where a between $j - 20 and $j;
|
||||
dec $size;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
connection con1;
|
||||
--disable_result_log
|
||||
--reap
|
||||
--enable_result_log
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
optimize table t1;
|
||||
select sleep(5);
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
select count(*) from t1;
|
||||
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
# After deletion & defragmentation, there are 8000 records left
|
||||
if (!`select count(*) < 180 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
# secondary index is pretty much the same size as primary index so the number of pages should be similar.
|
||||
if (!`select count(*) < 180 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
## Test-4 defragment with larger n_pages
|
||||
|
||||
# delete some more records
|
||||
--disable_query_log
|
||||
let $size = $delete_size;
|
||||
while ($size)
|
||||
{
|
||||
let $j = 100 * $size;
|
||||
eval delete from t1 where a between $j - 30 and $j - 20;
|
||||
dec $size;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
SET @@global.innodb_defragment_n_pages = 3;
|
||||
|
||||
# This will not reduce number of pages by a lot
|
||||
optimize table t1;
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
select count(*) from t1;
|
||||
|
||||
# We didn't create large wholes with the previous deletion, so if innodb_defragment_n_pages = 3, we won't be able to free up many pages.
|
||||
if (!`select count(*) > 130 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
# Same holds for secondary index, not many pages are released.
|
||||
if (!`select count(*) > 100 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
SET @@global.innodb_defragment_n_pages = 10;
|
||||
|
||||
optimize table t1;
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed', 'n_page_split', 'n_leaf_pages_defrag');
|
||||
|
||||
select count(*) from t1;
|
||||
|
||||
# This time we used innodb_defragment_n_pages = 10, so we should be able to free up some pages.
|
||||
if (!`select count(*) < 165 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY' order by page_number;
|
||||
}
|
||||
|
||||
select count(*) from t1 force index (second);
|
||||
|
||||
if (!`select count(*) < 165 from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;`)
|
||||
{
|
||||
select count(*) from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second' order by page_number;
|
||||
}
|
||||
|
||||
DROP PROCEDURE defragment;
|
||||
DROP TABLE t1;
|
||||
# reset system
|
||||
--disable_query_log
|
||||
EVAL SET GLOBAL innodb_defragment_n_pages = $innodb_defragment_n_pages_orig;
|
||||
EVAL SET GLOBAL innodb_defragment_stats_accuracy = $innodb_defragment_stats_accuracy_orig;
|
||||
--enable_query_log
|
||||
|
@ -0,0 +1,4 @@
|
||||
--loose-innodb-buffer-pool-stats
|
||||
--loose-innodb-buffer-page
|
||||
--loose-innodb-buffer-page-lru
|
||||
--innodb-defragment=1
|
130
mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test
Normal file
130
mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test
Normal file
@ -0,0 +1,130 @@
|
||||
--source include/have_innodb.inc
|
||||
--disable_warnings
|
||||
DROP TABLE if exists t1;
|
||||
DROP TABLE if exists t2;
|
||||
--enable_warnings
|
||||
--echo Testing tables with large records
|
||||
# Create table.
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB;
|
||||
# Populate table.
|
||||
let $i = 1000;
|
||||
--disable_query_log
|
||||
while ($i)
|
||||
{
|
||||
eval
|
||||
INSERT INTO t1 VALUES ($i, REPEAT('A', 256));
|
||||
dec $i;
|
||||
}
|
||||
--enable_query_log
|
||||
--disable_query_log
|
||||
let $size = 10;
|
||||
while ($size)
|
||||
{
|
||||
let $j = 100 * $size;
|
||||
eval delete from t1 where a between $j - 20 and $j;
|
||||
dec $size;
|
||||
}
|
||||
--enable_query_log
|
||||
optimize table t1;
|
||||
--source include/restart_mysqld.inc
|
||||
select count(*) from t1;
|
||||
# After deletion & defragmentation, there are 800 records left. Each page can hold about 57 records. We fill the page 90% full,
|
||||
# so there should be less than 16 pages total.
|
||||
--let $primary_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1)
|
||||
select count(*) from t1 force index (second);
|
||||
# secondary index is slightly bigger than primary index so the number of pages should be similar.
|
||||
--let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1)
|
||||
--echo # A few more insertions on the page should not cause a page split.
|
||||
insert into t1 values (81, REPEAT('A', 256));
|
||||
insert into t1 values (83, REPEAT('A', 256));
|
||||
insert into t1 values (87, REPEAT('A', 256));
|
||||
insert into t1 values (82, REPEAT('A', 256));
|
||||
insert into t1 values (86, REPEAT('A', 256));
|
||||
--let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1)
|
||||
--let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1)
|
||||
if ($primary_before != $primary_after) {
|
||||
--echo Insertion caused page split on primary, which should be avoided by innodb_defragment_fill_factor.
|
||||
}
|
||||
if ($second_before != $second_after) {
|
||||
--echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor.
|
||||
}
|
||||
--echo # More insertions will cause page splits
|
||||
insert into t1 values (88, REPEAT('A', 50));
|
||||
#insert into t1 values (85, REPEAT('A', 256));
|
||||
#insert into t1 values (84, REPEAT('A', 256));
|
||||
#insert into t1 values (89, REPEAT('A', 256));
|
||||
--let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1)
|
||||
--let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1)
|
||||
if ($primary_before == $primary_after) {
|
||||
--echo Too much space are reserved on primary index.
|
||||
}
|
||||
if ($second_before == $second_after) {
|
||||
--echo Too much space are reserved on second index.
|
||||
}
|
||||
DROP TABLE t1;
|
||||
--echo Testing table with small records
|
||||
CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARchar(16), KEY SECOND(a,b)) ENGINE=INNODB;
|
||||
# Populate table.
|
||||
--disable_query_log
|
||||
INSERT INTO t2 VALUES (1, REPEAT('A', 16));
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
INSERT INTO t2 (b) SELECT b from t2;
|
||||
--enable_query_log
|
||||
--disable_query_log
|
||||
let $size = 40;
|
||||
while ($size)
|
||||
{
|
||||
let $j = 100 * $size;
|
||||
eval delete from t2 where a between $j - 20 and $j;
|
||||
dec $size;
|
||||
}
|
||||
--enable_query_log
|
||||
optimize table t2;
|
||||
--source include/restart_mysqld.inc
|
||||
select count(*) from t2 force index(second);
|
||||
--let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1)
|
||||
--echo The page should have room for about 20 insertions
|
||||
insert into t2 values(1181, REPEAT('A', 16));
|
||||
insert into t2 values(1191, REPEAT('A', 16));
|
||||
insert into t2 values(1182, REPEAT('A', 16));
|
||||
insert into t2 values(1192, REPEAT('A', 16));
|
||||
insert into t2 values(1183, REPEAT('A', 16));
|
||||
insert into t2 values(1193, REPEAT('A', 16));
|
||||
insert into t2 values(1184, REPEAT('A', 16));
|
||||
insert into t2 values(1194, REPEAT('A', 16));
|
||||
insert into t2 values(1185, REPEAT('A', 16));
|
||||
insert into t2 values(1195, REPEAT('A', 16));
|
||||
insert into t2 values(1186, REPEAT('A', 16));
|
||||
insert into t2 values(1196, REPEAT('A', 16));
|
||||
insert into t2 values(1187, REPEAT('A', 16));
|
||||
insert into t2 values(1197, REPEAT('A', 16));
|
||||
insert into t2 values(1188, REPEAT('A', 16));
|
||||
insert into t2 values(1198, REPEAT('A', 16));
|
||||
insert into t2 values(1189, REPEAT('A', 16));
|
||||
insert into t2 values(1199, REPEAT('A', 16));
|
||||
insert into t2 values(1190, REPEAT('A', 16));
|
||||
insert into t2 values(1180, REPEAT('A', 16));
|
||||
--let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1)
|
||||
if ($second_before != $second_after) {
|
||||
--echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor.
|
||||
}
|
||||
--echo More insertions will cause page split.
|
||||
insert into t2 values(1280, REPEAT('A', 16));
|
||||
insert into t2 values(1290, REPEAT('A', 16));
|
||||
insert into t2 values(1281, REPEAT('A', 16));
|
||||
insert into t2 values(1291, REPEAT('A', 16));
|
||||
--let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1)
|
||||
if ($second_before == $second_after) {
|
||||
--echo Too much space are reserved on second index.
|
||||
}
|
||||
DROP TABLE t2;
|
Reference in New Issue
Block a user