1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES

Queries to INFORMATION_SCHEMA.PARAMETERS and ROUTINES tables are always
performed using full index scan of the mysql.proc primary key
on fields (`db`,`name`,`type`). This can be done in a much more effective
way if `db` and `name` field values can be derived from the WHERE statement,
like here:
  SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
    WHERE SPECIFIC_SCHEMA = 'test' AND SPECIFIC_NAME = 'my_func'
or here:
  SELECT * FROM information_schema.ROUTINES
    WHERE ROUTINE_SCHEMA='test' AND ROUTINE_NAME='my_func'.

In such cases index range scan may be employed instead of full index
scan. This commit makes the server retrieve lookup field values from
the SQL statement and perform index range scan instead of full index
scan if possible.
This commit is contained in:
Oleg Smirnov
2022-09-12 14:28:00 +07:00
parent 9206c1ea97
commit beb9a5459d
5 changed files with 638 additions and 38 deletions

View File

@@ -626,3 +626,168 @@ DTD_IDENTIFIER ROW
ROUTINE_TYPE PROCEDURE
-------- --------
DROP PROCEDURE p1;
#
# MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES
#
DROP DATABASE IF EXISTS i_s_parameters_test;
CREATE DATABASE i_s_parameters_test;
USE i_s_parameters_test;
CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30)
RETURN CONCAT('XYZ, ' ,s);
#
# We cannot use the index due to CONCAT()
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
WHERE CONCAT(SPECIFIC_SCHEMA) = 'i_s_parameters_test'
AND SPECIFIC_NAME = 'test_func5';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 0
PARAMETER_MODE NULL
PARAMETER_NAME NULL
DATA_TYPE varchar
CHARACTER_MAXIMUM_LENGTH 30
CHARACTER_OCTET_LENGTH 30
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER varchar(30)
ROUTINE_TYPE FUNCTION
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME s
DATA_TYPE char
CHARACTER_MAXIMUM_LENGTH 20
CHARACTER_OCTET_LENGTH 20
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER char(20)
ROUTINE_TYPE FUNCTION
SHOW STATUS LIKE 'handler_read%next';
Variable_name Value
Handler_read_next 54
Handler_read_rnd_next 97
#
# Now the index must be used
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
AND SPECIFIC_NAME = 'test_func5';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 0
PARAMETER_MODE NULL
PARAMETER_NAME NULL
DATA_TYPE varchar
CHARACTER_MAXIMUM_LENGTH 30
CHARACTER_OCTET_LENGTH 30
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER varchar(30)
ROUTINE_TYPE FUNCTION
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME s
DATA_TYPE char
CHARACTER_MAXIMUM_LENGTH 20
CHARACTER_OCTET_LENGTH 20
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER char(20)
ROUTINE_TYPE FUNCTION
SHOW STATUS LIKE 'handler_read%next';
Variable_name Value
Handler_read_next 1
Handler_read_rnd_next 3
#
# Using the first key part of the index
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 0
PARAMETER_MODE NULL
PARAMETER_NAME NULL
DATA_TYPE varchar
CHARACTER_MAXIMUM_LENGTH 30
CHARACTER_OCTET_LENGTH 30
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER varchar(30)
ROUTINE_TYPE FUNCTION
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME test_func5
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME s
DATA_TYPE char
CHARACTER_MAXIMUM_LENGTH 20
CHARACTER_OCTET_LENGTH 20
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME latin1
COLLATION_NAME latin1_swedish_ci
DTD_IDENTIFIER char(20)
ROUTINE_TYPE FUNCTION
SHOW STATUS LIKE 'handler_read%next';
Variable_name Value
Handler_read_next 1
Handler_read_rnd_next 3
#
# Test non-latin letters in procedure name
SET NAMES koi8r;
CREATE PROCEDURE `процедурка`(a INT) SELECT a;
#
# The index must be used
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
AND SPECIFIC_NAME = 'процедурка';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA i_s_parameters_test
SPECIFIC_NAME процедурка
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME a
DATA_TYPE int
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION 10
NUMERIC_SCALE 0
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER int(11)
ROUTINE_TYPE PROCEDURE
SHOW STATUS LIKE 'handler_read%next';
Variable_name Value
Handler_read_next 1
Handler_read_rnd_next 2
DROP DATABASE i_s_parameters_test;
USE test;