[MDEV-12581] Querying INFORMATION_SCHEMA.PARTITIONS becomes extremely slow in 10.1.19 and 10.1.22 Created: 2017-04-24  Updated: 2017-11-05  Resolved: 2017-11-05

Status: Closed
Project: MariaDB Server
Component/s: Partitioning
Affects Version/s: 10.1.19, 10.1.22
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: HwaYou Hsu Assignee: Unassigned
Resolution: Incomplete Votes: 1
Labels: need_feedback


 Description   

Issue :

When querying INFORMATION_SCHEMA.PARTITIONS table for a partition that does not exist, the query takes very long time to return:
For example, the following query would take long time for the table defined below:

SELECT 1 FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'PartitionTable' AND PARTITION_NAME = 'P1493057460'

We have a partitioned table that is using RANGE partitioning. We use the the bigint(20) column 'utime' to represent the epoch timestamp of a record.

*************************** 1. row ***************************
       Table: PartitionTable
Create Table: CREATE TABLE `PartitionTable` (
  `rule_id` int(10) unsigned NOT NULL,
  `rev` int(10) unsigned DEFAULT NULL COMMENT 'revision number',
  `utime` bigint(20) unsigned DEFAULT '0',
  `s0` varchar(128) NOT NULL,
  `s1` varchar(128) NOT NULL,
  `s2` varchar(128) DEFAULT NULL,
  `s3` varchar(128) DEFAULT NULL,
  `s4` varchar(128) DEFAULT NULL,
  `s5` varchar(128) DEFAULT NULL,
  `s6` varchar(128) DEFAULT NULL,
  `s7` varchar(128) DEFAULT NULL,
  `r0` text NOT NULL,
  `r1` text NOT NULL,
  `r2` text,
  `r3` text,
  `r4` text,
  `r5` text,
  KEY `match_all` (`rule_id`,`rev`,`s0`,`s1`,`s2`,`s3`,`s4`,`s5`,`s6`,`s7`,`utime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (utime)
(PARTITION P1493056200 VALUES LESS THAN (1493056260) ENGINE = InnoDB,
 PARTITION P1493056260 VALUES LESS THAN (1493056320) ENGINE = InnoDB,
 PARTITION P1493056320 VALUES LESS THAN (1493056380) ENGINE = InnoDB,
 PARTITION P1493056380 VALUES LESS THAN (1493056440) ENGINE = InnoDB,
 PARTITION P1493056440 VALUES LESS THAN (1493056500) ENGINE = InnoDB,
 PARTITION P1493056500 VALUES LESS THAN (1493056560) ENGINE = InnoDB,
 PARTITION P1493056560 VALUES LESS THAN (1493056620) ENGINE = InnoDB,
 PARTITION P1493056620 VALUES LESS THAN (1493056680) ENGINE = InnoDB,
 PARTITION P1493056680 VALUES LESS THAN (1493056740) ENGINE = InnoDB,
 PARTITION P1493056740 VALUES LESS THAN (1493056800) ENGINE = InnoDB,
 PARTITION P1493056800 VALUES LESS THAN (1493056860) ENGINE = InnoDB,
 PARTITION P1493056860 VALUES LESS THAN (1493056920) ENGINE = InnoDB,
 PARTITION P1493056920 VALUES LESS THAN (1493056980) ENGINE = InnoDB,
 PARTITION P1493056980 VALUES LESS THAN (1493057040) ENGINE = InnoDB,
 PARTITION P1493057040 VALUES LESS THAN (1493057100) ENGINE = InnoDB,
 PARTITION P1493057100 VALUES LESS THAN (1493057160) ENGINE = InnoDB,
 PARTITION P1493057160 VALUES LESS THAN (1493057220) ENGINE = InnoDB,
 PARTITION P1493057220 VALUES LESS THAN (1493057280) ENGINE = InnoDB,
 PARTITION P1493057280 VALUES LESS THAN (1493057340) ENGINE = InnoDB,
 PARTITION P1493057340 VALUES LESS THAN (1493057400) ENGINE = InnoDB,
 PARTITION P1493057400 VALUES LESS THAN (1493057460) ENGINE = InnoDB) */
1 row in set (0.00 sec)

We have an application that inserts contantly into the table using prepared statments. Each partition will end up with around 200k records (ie, 200k entries inserted in one minutes)

Every hour we create 60 new partitions for the table, and then drop the all the partitions that are created more than two hours ago:

Partition Creation:

We first get the latest partition's upper limit, and store it in p_start_time

SELECT MAX(CAST(PARTITION_DESCRIPTION AS UNSIGNED)) FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'PartitionTable';

We then have name of the new partition by CONCAT'ing 'P' and the timestamp. Next, we check the existence of a new partition. If the new partition does not exist ("SELECT 1" returns 0"), then we create the new partition.

SELECT 1 FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'PartitionTable' AND PARTITION_NAME = CONCAT('P',p_start_time) INTO p_exists;
IF (p_exists < 1) THEN
	SET @sql := CONCAT('ALTER IGNORE TABLE `test`.`PartitionTable`  ADD PARTITION ( PARTITION P', p_start_time ,' VALUES LESS THAN (',p_start_time +   60,') );');
	PREPARE stmt FROM @sql;
	EXECUTE stmt;
	DEALLOCATE PREPARE stmt;
END IF;

We increament p_start_time value and repeat the above operation for 60 times, thus create 60 new partitions.

Partition Drop:

We then run

 ALTER TABLE test.PartitionTable DROP PARTITION <partition_name> 

repeatly to drop all partitions that are more than two hours old.

After upgrading from 10.1.15 to 10.1.19 and to 10.1.22, we are seeing that the query in the partition creation part

SELECT 1 FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'PartitionTable' AND PARTITION_NAME = CONCAT('P',p_start_time)

now takes very long time to complete, more than 20 seconds or even longer.
However, once a partition is created, such query would return in no time (around 0.05 seconds or so when measured by bash time builtin function).

my.cnf:

[mysqld]
datadir=/var/mysql/data
socket=/var/lib/mysql/mysql.sock
user=mysql
skip-name-resolve
tmpdir=/var/tmp/mysql
innodb_fast_shutdown=0
sql_mode=
pid-file=/var/run/mysqld/mysqld.pid
 
auto_increment_offset=1
max_allowed_packet=67108864
long_query_time=0
innodb_write_io_threads=64
innodb_autoinc_lock_mode=2
max_prepared_stmt_count=65528
table_cache=2048
thread_cache_size=500
table_definition_cache=400
max_connections=8000
innodb_log_buffer_size=32M
event_scheduler=ON
innodb_flush_method=O_DIRECT
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=0
key_buffer_size=128M
query_cache_type=0
innodb_file_per_table=1
myisam-recover=FORCE,BACKUP
bind_address=127.0.0.1
innodb_io_capacity=100
query_cache_size=0
innodb_log_file_size=512M
innodb_stats_on_metadata=OFF
auto_increment_increment=1
innodb_buffer_pool_size=8G
innodb_support_xa=false
 
 
[mysqld_safe]
pid-file=/var/run/mysqld/mysqld.pid



 Comments   
Comment by HwaYou Hsu [ 2017-05-04 ]

We have found the root cause of the issue and this bug can be closed as invalid.

The slow down was caused by using glibc malloc instead of libjemalloc.

Once we started using libjemalloc again we saw it jumped back to its old performance.

Comment by Sergei Golubchik [ 2017-05-04 ]

This is interesting. In all our benchmarks we failed to see any noticeable speedup caused by jemalloc as compared to system glibc malloc. What storage engines do you use?

Do you use self-compiled binaries? Our 10.1 binaries always use jemalloc.

Comment by HwaYou Hsu [ 2017-05-05 ]

We use the default storage engine, XtraDB.

Yes we build our own binaries.

Comment by Elena Stepanova [ 2017-06-09 ]

hhsu,
Could you please paste your build options, and also specify the environment?
Is it the only partitioned table?
Is there any activity on the table at the time when your SELECT from I_S is executed?
Can you paste the whole body of the procedure?
Thanks.

Comment by Elena Stepanova [ 2017-08-08 ]

hhsu,

There has been a bit of diversion, so I'll re-iterate the question.

Could you please paste your build options, and also specify the environment?
Is it the only partitioned table?
Is there any activity on the table at the time when your SELECT from I_S is executed?
Can you paste the whole body of the procedure?

Thanks.

Generated at Thu Feb 08 07:58:50 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.