Bug #115062 Guidelines for estimating range optimization memory usage inaccurate
Submitted: 20 May 11:02 Modified: 20 May 11:33
Reporter: Przemyslaw Malkowski Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any
Tags: range_optimizer_max_mem_size

[20 May 11:02] Przemyslaw Malkowski
Description:
Hello MySQL Team!

The documented guidelines we can find here:
https://dev.mysql.com/doc/refman/8.0/en/range-optimization.html#range-optimization-memory-...
suggest that we could expect about 230 bytes per predicate in a simple IN (1,2...N) query. However, when we check the real amount used, as advised in:
https://bugs.mysql.com/bug.php?id=78752, it turns out to be much more than that.

How to repeat:
Populate a simple sysbench table:

mysql> show create table sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int NOT NULL AUTO_INCREMENT,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `pad` (`pad`)
) ENGINE=InnoDB AUTO_INCREMENT=2024 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql > truncate table performance_schema.memory_summary_by_thread_by_event_name;
Query OK, 0 rows affected (0.00 sec)

mysql > select * from performance_schema.memory_summary_by_thread_by_event_name where thread_id=PS_CURRENT_THREAD_ID() and event_name='memory/sql/test_quick_select'\G
*************************** 1. row ***************************
                   THREAD_ID: 47
                  EVENT_NAME: memory/sql/test_quick_select
                 COUNT_ALLOC: 0
                  COUNT_FREE: 0
   SUM_NUMBER_OF_BYTES_ALLOC: 0
    SUM_NUMBER_OF_BYTES_FREE: 0
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 0
             HIGH_COUNT_USED: 0
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 0
   HIGH_NUMBER_OF_BYTES_USED: 0
1 row in set (0.00 sec)

mysql > select count(*) from sbtest1 where id in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100);
+----------+
| count(*) |
+----------+
|      100 |
+----------+
1 row in set (0.01 sec)

mysql > select * from performance_schema.memory_summary_by_thread_by_event_name where thread_id=PS_CURRENT_THREAD_ID() and event_name='memory/sql/test_quick_select'\G
*************************** 1. row ***************************
                   THREAD_ID: 47
                  EVENT_NAME: memory/sql/test_quick_select
                 COUNT_ALLOC: 5
                  COUNT_FREE: 5
   SUM_NUMBER_OF_BYTES_ALLOC: 54256
    SUM_NUMBER_OF_BYTES_FREE: 54256
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 0
             HIGH_COUNT_USED: 5
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 0
   HIGH_NUMBER_OF_BYTES_USED: 54256
1 row in set (0.00 sec)

So, 542 bytes instead of 230 here! 
Indeed, lowering the memory limit below the P_S reported value disables the optimization:

mysql > set range_optimizer_max_mem_size=54000;
Query OK, 0 rows affected (0.00 sec)

mysql > select count(*) from sbtest1 where id in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100);
+----------+
| count(*) |
+----------+
|      100 |
+----------+
1 row in set, 1 warning (0.00 sec)

mysql > show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                     |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
| Warning | 3170 | Memory capacity of 54000 bytes for 'range_optimizer_max_mem_size' exceeded. Range optimization was not done for this query. |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Interestingly, when a non-related secondary key is dropped, the memory requirement goes down:

mysql > alter table sbtest1 drop key pad;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql > truncate table performance_schema.memory_summary_by_thread_by_event_name;
Query OK, 0 rows affected (0.00 sec)

mysql > select count(*) from sbtest1 where id in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100);
+----------+
| count(*) |
+----------+
|      100 |
+----------+
1 row in set (0.00 sec)

mysql > select * from performance_schema.memory_summary_by_thread_by_event_name where thread_id=PS_CURRENT_THREAD_ID() and event_name='memory/sql/test_quick_select'\G
*************************** 1. row ***************************
                   THREAD_ID: 67
                  EVENT_NAME: memory/sql/test_quick_select
                 COUNT_ALLOC: 4
                  COUNT_FREE: 4
   SUM_NUMBER_OF_BYTES_ALLOC: 33472
    SUM_NUMBER_OF_BYTES_FREE: 33472
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 0
             HIGH_COUNT_USED: 4
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 0
   HIGH_NUMBER_OF_BYTES_USED: 33472
1 row in set (0.00 sec)

But, still higher than 230 bytes.

Suggested fix:
Provide more accurate memory guidelines for range optimization.
[20 May 11:33] MySQL Verification Team
Hi Mr. Malkowski,

Thank you for your bug report.

We have ran your tests and we agree with your conclusion.

This is now a verified and very important Documentation bug.

Affecting version 8.0 and higher.