MySQL Performance FIND_IN_SET

NIRAV SHAH
2 min readFeb 17, 2021

--

MySQL Database is being used for various analytical queries. Some of the frequent query we have is get table data from list of values. It is prominent to use FIND_IN_SET function, as it does not require any query change.

Before MySQL 5.7 , It does not support function indexes. Hence whenever we query with function on column it will go for full table scan.

Below is dummy table example for showing the same thing. however, we need to add huge data set to prove same. Volumatric part will be done later. Let’s check sample query.

Sample Data generation

# Setup table & datacreate table tbl(i int, b varchar(23));
insert into tbl values(1,'2'),(2,'sdf');
insert into tbl values(3,'new'),(4,'zxf');
alter table tbl add index idx_i(i);
alter table tbl add index idx_b(b);

Original procedure with FIND_IN_SET

DROP PROCEDURE IF EXISTS proc_find_in_set;
delimiter //
CREATE PROCEDURE proc_find_in_set(item varchar(245))
BEGIN
select * from tbl where FIND_IN_SET(i,item);
END//
delimiter ;
call proc_find_in_set('1');
call proc_find_in_set('1,3');

Although above does good job for integer & string both, It is not using index & hence degrade the database performance overall. Let’s convert it in IN query, so that it uses index.

Convert FIND_IN_SET to IN query for int

DROP PROCEDURE IF EXISTS proc_in_int;
delimiter //
CREATE PROCEDURE proc_in_int(item varchar(245))
BEGIN
SET @query1:=concat("select * from tbl where i in (",item,')');
PREPARE stmt FROM @query1;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END//
delimiter ;
call proc_in_int('1');
call proc_in_int('1,3');

The quey works without any major change. We added only prepared statement for dynamic value resolution. However, for varchar same query may not work. We have to use string operation to convert value stream with quoted values.

Convert FIND_IN_SET to IN query for string

DROP PROCEDURE IF EXISTS proc_in_str;
delimiter //
CREATE PROCEDURE proc_in_str(item varchar(245))
BEGIN
SET @Itemfilter := CONCAT("'",replace(item,",","','"),"'");
SET @query1:=concat("select * from tbl where b in (",@Itemfilter,')');
PREPARE stmt FROM @query1;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END//
delimiter ;
call proc_in_str('sdf,2');
call proc_in_str('sdf');

That’s it! Your application now 10x faster as it will use indexes.

--

--

NIRAV SHAH
NIRAV SHAH

Written by NIRAV SHAH

Working as Cloud Architect & Software enthusiastic

No responses yet