函数索引优化

110 阅读1分钟

MySQL函数索引优化

SQL示例1

原始SQL使用了函数lower导致索引失效,花费时间2s以上,优化之后可以达到0.001s

SELECT
	t0.id,
	t0.email,
	t0.mobile,
	t0.state,
	t0.bw_password,
	t0.bw_salt,
	t0.bwplus_password,
	t0.bwplus_salt,
	t0.app_id,
	t0.last_login_time,
	t0.bind_email_time,
	t0.bind_mobile_time,
	t0.activate_time,
	t0.create_time,
	t0.update_time,
	t1.id 
FROM
	newsso.tb_user t0
	LEFT JOIN newsso.bw_user_level t1 ON t1.user_id = t0.id 
WHERE
	( lower( t0.email ) LIKE 'xxxxx@gmail.com%' ESCAPE '' 
     OR 
     lower( t0.mobile ) LIKE 'xxxxx@gmail.com' ESCAPE '' ) 
	LIMIT 10

优化之后

可以建立函数索引,首先将运算之后的结果变成虚拟列插入到tb_user中,然后对虚拟列建立索引。

 alter table tb_user add column lower_email varchar(256) GENERATED ALWAYS AS (lower(email));
 alter table tb_user add column lower_mobile varchar(32) GENERATED ALWAYS AS (lower(mobile));

 alter table tb_user add index tb_user_function_of_email(lower_email);
 
 alter table tb_user add index tb_user_function_of_mobile(lower_mobile);


explain SELECT
 t0.id,
 t0.email,
 t0.mobile,
 t0.state,
 t0.bw_password,
 t0.bw_salt,
 t0.bwplus_password,
 t0.bwplus_salt,
 t0.app_id,
 t0.last_login_time,
 t0.bind_email_time,
 t0.bind_mobile_time,
 t0.activate_time,
 t0.create_time,
 t0.update_time,
 t1.id 
FROM
 tb_user t0
 LEFT JOIN bw_user_level t1 ON t1.user_id = t0.id 
WHERE
 ( t0.lower_email LIKE 'xxxxx@gmail.com%' ESCAPE '' ) 
 OR ( t0.lower_mobile LIKE 'xxxxx@gmail.com' ESCAPE '' ) 
 LIMIT 10
从原来的2.26s降低到0.001s

SQL示例2

select count(*) from newsso.tb_user t0 where (lower(t0.email) like '0978341138%' escape''  or lower(t0.mobile) like '0978341138' escape'' )

优化之后

EXPLAIN SELECT
 count(*) 
FROM
 tb_user t0 
WHERE
 (
   t0.lower_email  LIKE '0978341138%' ESCAPE '' 
  OR t0.lower_mobile LIKE '0978341138' ESCAPE '' 
 )
 
 alter table tb_user add column lower_email varchar(256) GENERATED ALWAYS AS (lower(email));
 alter table tb_user add column lower_mobile varchar(32) GENERATED ALWAYS AS (lower(mobile));

 alter table tb_user add index tb_user_function_of_email(lower_email);
 
 alter table tb_user add index tb_user_function_of_mobile(lower_mobile);

本地优化之后从原来的1.5s降到0.005s