上午朋友问我一条sql优化方案,因采用or全表扫描查询,导致查询速度过慢(2s多),问我有没有优化方案,具体sql如下:
set @search = 'yd12015';
SELECT `pwd_flag`,`username`,`uid`,`email`,`user_status` FROM `member` WHERE
(
`user_status` >=0 and `email_status`=0 and (`username`=@search or `email`=@search or `phone`=@search)
) LIMIT 1;
逻辑意思为:查询用户表审核通过&&未锁定&&(用户名或者邮箱或者电话号码为具体字符串)的用户信息,放在自己服务器上测试,当menber表数据量达到100w级别时,查询耗时大约在1.5s左右,这是在没有并发的情况,如果存在并发,那就没得救了。得优化!
仔细思考这条sql需要得到的用户数据,发现是可以有优化方案的,首先想到的是用union查询,然后得到的sql如下:
set @search = 'yd12015';
SELECT `pwd_flag`,`username`,`uid`,`email`,`user_status` FROM `member` WHERE
(
`user_status` >=0 and `email_status`=0 and `username`=@search
)
union
SELECT `pwd_flag`,`username`,`uid`,`email`,`user_status` FROM `member` WHERE
(
`user_status` >=0 and `email_status`=0 and `email`=@search
)
union
SELECT `pwd_flag`,`username`,`uid`,`email`,`user_status` FROM `member` WHERE
(
`user_status` >=0 and `email_status`=0 and `phone`=@search
)
limit 1
检测查询时间,瞬间将至0.1s以下,这是妥妥的性能提升啊,可取!
第二个方案是,根据查询字符串,优化查询sql,因查询的是用户名,邮箱,电话,所以可以先判断字符串的类型,来查询对应的字段,比如,如果既不是邮箱,也不是电话,就没必要去扫描这2个字段了。如果单纯是邮箱格式,那就不可能是电话号码。
注:union的用法及一些需要注意事项:
union:联合的意思,即把两次或多次查询结果合并起来。