Skip to content

Commit beb9a54

Browse files
committed
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.
1 parent 9206c1e commit beb9a54

File tree

5 files changed

+636
-36
lines changed

5 files changed

+636
-36
lines changed

mysql-test/main/information_schema_parameters.result

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,3 +626,168 @@ DTD_IDENTIFIER ROW
626626
ROUTINE_TYPE PROCEDURE
627627
-------- --------
628628
DROP PROCEDURE p1;
629+
#
630+
# MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES
631+
#
632+
DROP DATABASE IF EXISTS i_s_parameters_test;
633+
CREATE DATABASE i_s_parameters_test;
634+
USE i_s_parameters_test;
635+
CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30)
636+
RETURN CONCAT('XYZ, ' ,s);
637+
#
638+
# We cannot use the index due to CONCAT()
639+
FLUSH STATUS;
640+
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
641+
WHERE CONCAT(SPECIFIC_SCHEMA) = 'i_s_parameters_test'
642+
AND SPECIFIC_NAME = 'test_func5';
643+
SPECIFIC_CATALOG def
644+
SPECIFIC_SCHEMA i_s_parameters_test
645+
SPECIFIC_NAME test_func5
646+
ORDINAL_POSITION 0
647+
PARAMETER_MODE NULL
648+
PARAMETER_NAME NULL
649+
DATA_TYPE varchar
650+
CHARACTER_MAXIMUM_LENGTH 30
651+
CHARACTER_OCTET_LENGTH 30
652+
NUMERIC_PRECISION NULL
653+
NUMERIC_SCALE NULL
654+
DATETIME_PRECISION NULL
655+
CHARACTER_SET_NAME latin1
656+
COLLATION_NAME latin1_swedish_ci
657+
DTD_IDENTIFIER varchar(30)
658+
ROUTINE_TYPE FUNCTION
659+
SPECIFIC_CATALOG def
660+
SPECIFIC_SCHEMA i_s_parameters_test
661+
SPECIFIC_NAME test_func5
662+
ORDINAL_POSITION 1
663+
PARAMETER_MODE IN
664+
PARAMETER_NAME s
665+
DATA_TYPE char
666+
CHARACTER_MAXIMUM_LENGTH 20
667+
CHARACTER_OCTET_LENGTH 20
668+
NUMERIC_PRECISION NULL
669+
NUMERIC_SCALE NULL
670+
DATETIME_PRECISION NULL
671+
CHARACTER_SET_NAME latin1
672+
COLLATION_NAME latin1_swedish_ci
673+
DTD_IDENTIFIER char(20)
674+
ROUTINE_TYPE FUNCTION
675+
SHOW STATUS LIKE 'handler_read%next';
676+
Variable_name Value
677+
Handler_read_next 54
678+
Handler_read_rnd_next 97
679+
#
680+
# Now the index must be used
681+
FLUSH STATUS;
682+
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
683+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
684+
AND SPECIFIC_NAME = 'test_func5';
685+
SPECIFIC_CATALOG def
686+
SPECIFIC_SCHEMA i_s_parameters_test
687+
SPECIFIC_NAME test_func5
688+
ORDINAL_POSITION 0
689+
PARAMETER_MODE NULL
690+
PARAMETER_NAME NULL
691+
DATA_TYPE varchar
692+
CHARACTER_MAXIMUM_LENGTH 30
693+
CHARACTER_OCTET_LENGTH 30
694+
NUMERIC_PRECISION NULL
695+
NUMERIC_SCALE NULL
696+
DATETIME_PRECISION NULL
697+
CHARACTER_SET_NAME latin1
698+
COLLATION_NAME latin1_swedish_ci
699+
DTD_IDENTIFIER varchar(30)
700+
ROUTINE_TYPE FUNCTION
701+
SPECIFIC_CATALOG def
702+
SPECIFIC_SCHEMA i_s_parameters_test
703+
SPECIFIC_NAME test_func5
704+
ORDINAL_POSITION 1
705+
PARAMETER_MODE IN
706+
PARAMETER_NAME s
707+
DATA_TYPE char
708+
CHARACTER_MAXIMUM_LENGTH 20
709+
CHARACTER_OCTET_LENGTH 20
710+
NUMERIC_PRECISION NULL
711+
NUMERIC_SCALE NULL
712+
DATETIME_PRECISION NULL
713+
CHARACTER_SET_NAME latin1
714+
COLLATION_NAME latin1_swedish_ci
715+
DTD_IDENTIFIER char(20)
716+
ROUTINE_TYPE FUNCTION
717+
SHOW STATUS LIKE 'handler_read%next';
718+
Variable_name Value
719+
Handler_read_next 1
720+
Handler_read_rnd_next 3
721+
#
722+
# Using the first key part of the index
723+
FLUSH STATUS;
724+
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
725+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test';
726+
SPECIFIC_CATALOG def
727+
SPECIFIC_SCHEMA i_s_parameters_test
728+
SPECIFIC_NAME test_func5
729+
ORDINAL_POSITION 0
730+
PARAMETER_MODE NULL
731+
PARAMETER_NAME NULL
732+
DATA_TYPE varchar
733+
CHARACTER_MAXIMUM_LENGTH 30
734+
CHARACTER_OCTET_LENGTH 30
735+
NUMERIC_PRECISION NULL
736+
NUMERIC_SCALE NULL
737+
DATETIME_PRECISION NULL
738+
CHARACTER_SET_NAME latin1
739+
COLLATION_NAME latin1_swedish_ci
740+
DTD_IDENTIFIER varchar(30)
741+
ROUTINE_TYPE FUNCTION
742+
SPECIFIC_CATALOG def
743+
SPECIFIC_SCHEMA i_s_parameters_test
744+
SPECIFIC_NAME test_func5
745+
ORDINAL_POSITION 1
746+
PARAMETER_MODE IN
747+
PARAMETER_NAME s
748+
DATA_TYPE char
749+
CHARACTER_MAXIMUM_LENGTH 20
750+
CHARACTER_OCTET_LENGTH 20
751+
NUMERIC_PRECISION NULL
752+
NUMERIC_SCALE NULL
753+
DATETIME_PRECISION NULL
754+
CHARACTER_SET_NAME latin1
755+
COLLATION_NAME latin1_swedish_ci
756+
DTD_IDENTIFIER char(20)
757+
ROUTINE_TYPE FUNCTION
758+
SHOW STATUS LIKE 'handler_read%next';
759+
Variable_name Value
760+
Handler_read_next 1
761+
Handler_read_rnd_next 3
762+
#
763+
# Test non-latin letters in procedure name
764+
SET NAMES koi8r;
765+
CREATE PROCEDURE `процедурка`(a INT) SELECT a;
766+
#
767+
# The index must be used
768+
FLUSH STATUS;
769+
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
770+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
771+
AND SPECIFIC_NAME = 'процедурка';
772+
SPECIFIC_CATALOG def
773+
SPECIFIC_SCHEMA i_s_parameters_test
774+
SPECIFIC_NAME процедурка
775+
ORDINAL_POSITION 1
776+
PARAMETER_MODE IN
777+
PARAMETER_NAME a
778+
DATA_TYPE int
779+
CHARACTER_MAXIMUM_LENGTH NULL
780+
CHARACTER_OCTET_LENGTH NULL
781+
NUMERIC_PRECISION 10
782+
NUMERIC_SCALE 0
783+
DATETIME_PRECISION NULL
784+
CHARACTER_SET_NAME NULL
785+
COLLATION_NAME NULL
786+
DTD_IDENTIFIER int(11)
787+
ROUTINE_TYPE PROCEDURE
788+
SHOW STATUS LIKE 'handler_read%next';
789+
Variable_name Value
790+
Handler_read_next 1
791+
Handler_read_rnd_next 2
792+
DROP DATABASE i_s_parameters_test;
793+
USE test;

mysql-test/main/information_schema_parameters.test

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,56 @@ DELIMITER ;$$
276276
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1';
277277
--horizontal_results
278278
DROP PROCEDURE p1;
279+
280+
281+
--echo #
282+
--echo # MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES
283+
--echo #
284+
--disable_warnings
285+
DROP DATABASE IF EXISTS i_s_parameters_test;
286+
--enable_warnings
287+
288+
CREATE DATABASE i_s_parameters_test;
289+
USE i_s_parameters_test;
290+
291+
CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30)
292+
RETURN CONCAT('XYZ, ' ,s);
293+
294+
--echo #
295+
--echo # We cannot use the index due to CONCAT()
296+
FLUSH STATUS;
297+
query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
298+
WHERE CONCAT(SPECIFIC_SCHEMA) = 'i_s_parameters_test'
299+
AND SPECIFIC_NAME = 'test_func5';
300+
SHOW STATUS LIKE 'handler_read%next';
301+
302+
--echo #
303+
--echo # Now the index must be used
304+
FLUSH STATUS;
305+
query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
306+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
307+
AND SPECIFIC_NAME = 'test_func5';
308+
SHOW STATUS LIKE 'handler_read%next';
309+
310+
--echo #
311+
--echo # Using the first key part of the index
312+
FLUSH STATUS;
313+
query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
314+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test';
315+
SHOW STATUS LIKE 'handler_read%next';
316+
317+
--echo #
318+
--echo # Test non-latin letters in procedure name
319+
SET NAMES koi8r;
320+
CREATE PROCEDURE `процедурка`(a INT) SELECT a;
321+
--echo #
322+
--echo # The index must be used
323+
FLUSH STATUS;
324+
query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS
325+
WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'
326+
AND SPECIFIC_NAME = 'процедурка';
327+
SHOW STATUS LIKE 'handler_read%next';
328+
329+
# Cleanup
330+
DROP DATABASE i_s_parameters_test;
331+
USE test;

0 commit comments

Comments
 (0)