From 6bd23caf5596722ca4a4f64995640a86c71dc593 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Mon, 15 Apr 2024 14:17:46 +0000 Subject: [PATCH] Improve performance for `BaseShowTablesWithSizes` query. Signed-off-by: Arthur Schreiber --- go/mysql/flavor_mysql.go | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/go/mysql/flavor_mysql.go b/go/mysql/flavor_mysql.go index c0a06540368..2d9471130dd 100644 --- a/go/mysql/flavor_mysql.go +++ b/go/mysql/flavor_mysql.go @@ -329,31 +329,15 @@ GROUP BY t.table_name, t.table_type, t.create_time, t.table_comment` // TablesWithSize80 is a query to select table along with size for mysql 8.0 // -// We join with a subquery that materializes the data from `information_schema.innodb_sys_tablespaces` -// early for performance reasons. This effectively causes only a single read of `information_schema.innodb_tablespaces` -// per query. // Note the following: -// - We use UNION ALL to deal differently with partitioned tables vs. non-partitioned tables. -// Originally, the query handled both, but that introduced "WHERE ... OR" conditions that led to poor query -// optimization. By separating to UNION ALL we remove all "OR" conditions. +// - We use a single query to fetch both partitioned and non-partitioned tables. This is because +// accessing `information_schema.innodb_tablespaces` is expensive on servers with many tables, +// and every query that loads the table needs to perform full table scans on it. Doing a single +// table scan is more efficient than doing more than one. // - We utilize `INFORMATION_SCHEMA`.`TABLES`.`CREATE_OPTIONS` column to do early pruning before the JOIN. // - `TABLES`.`TABLE_NAME` has `utf8mb4_0900_ai_ci` collation. `INNODB_TABLESPACES`.`NAME` has `utf8mb3_general_ci`. // We normalize the collation to get better query performance (we force the casting at the time of our choosing) -// - `create_options` is NULL for views, and therefore we need an additional UNION ALL to include views const TablesWithSize80 = `SELECT t.table_name, - t.table_type, - UNIX_TIMESTAMP(t.create_time), - t.table_comment, - i.file_size, - i.allocated_size - FROM information_schema.tables t - LEFT JOIN information_schema.innodb_tablespaces i - ON i.name = CONCAT(t.table_schema, '/', t.table_name) COLLATE utf8mb3_general_ci - WHERE - t.table_schema = database() AND not t.create_options <=> 'partitioned' -UNION ALL - SELECT - t.table_name, t.table_type, UNIX_TIMESTAMP(t.create_time), t.table_comment, @@ -361,9 +345,9 @@ UNION ALL SUM(i.allocated_size) FROM information_schema.tables t LEFT JOIN information_schema.innodb_tablespaces i - ON i.name LIKE (CONCAT(t.table_schema, '/', t.table_name, '#p#%') COLLATE utf8mb3_general_ci ) + ON i.name LIKE CONCAT(t.table_schema, '/', t.table_name, IF(t.create_options <=> 'partitioned', '#p#%', '')) COLLATE utf8mb3_general_ci WHERE - t.table_schema = database() AND t.create_options <=> 'partitioned' + t.table_schema = database() GROUP BY t.table_schema, t.table_name, t.table_type, t.create_time, t.table_comment `