因为一直是给政府做系统,基本上用户量很少,所以做了几个系统都没有想到去优化数据库的查询速度,但是最近一个刚上线的某行业翻译系统没有推广却有了不少的用户使用,然后数据库在翻译记录达到了十万条的时候出现了查询速度变慢的情况,翻译一个单词都需要十几秒时间。
因为奇葩设定,用户使用翻译功能前没有登录的需要根据IP查询免费使用的词数不能超过三百字/日,登录后单个ID不能超过五千字/日,所以需要在翻译前查询一次。
排查了服务器与翻译引擎之间网络的问题后确认了问题的根源出在了数据库上,所以首先想到的就是去看看sql语句的问题。渣渣sql语句如下:
# 根据用户id查询用户今日翻译原文本的长度
select * from translation_record where user_id=#{userId}
and to_days(create_time) = to_days(now());
# 根据用户IP查询用户今日翻译原文本的长度
select * from translation_record where user_ip=#{userIp}
and to_days(create_time) = to_days(now());
首先就是结果集使用的*,这里是不合理,因为只需要统计用户今天翻译使用的字数,所以只需要返回文本长度和用户ID或IP即可。
另外这里使用到了日期转换函数to_days(),在查询中最好避免使用sql提供的函数,可以提前使用java处理好之后再做查询。
优化后的sql如下,根据id的类似:
select user_ip as userIp, length as length from fanyi_record
where
user_ip=#{userIp}
and create_time > #{startTime}
and create_time < #{endTime}
然后查看数据库结构,可以看到除了主键id之外没有添加任何索引。
给user_id和user_ip两个字段添加普通索引,打包发布上测试环境,十万行翻译记录的情况下基本秒通过。因为一直以来开发的系统都没有用户,所以也算是第一次尝试使用索引这个东西,渣渣记录下,有不正确的地方还望指出。