select a.*,b.address from vinfo_visit_log_temp a left join address_ip b on to_number(getAreaByIp(a.visit_ip)) between b.startip and b.endipvinfo_visit_log_temp 表中数据中有15w条数据(a.visit_ip是varchar2,比如192.168.0.102,getAreaByIp函数为自定义,是计算出ip对应的number)
address_ip中有26w条数据,表结构 startip:number,endip:number,address:varchar2(地方名,比如河南省)现在这条sql语句的目的是查出vinfo_visit_log_temp每条访问记录的来源地方名有没有执行效率更高些的sql语句
address_ip中有26w条数据,表结构 startip:number,endip:number,address:varchar2(地方名,比如河南省)现在这条sql语句的目的是查出vinfo_visit_log_temp每条访问记录的来源地方名有没有执行效率更高些的sql语句
to_number(getAreaByIp(a.visit_ip)) between b.startip and b.endip
上了,全表扫描了a表,没有调用索引
select a.*,b.address from vinfo_visit_log_temp a left join address_ip b on to_number(getAreaByIp(a.visit_ip)) between b.startip and b.endip
/
@?/rdbms/admin/utlxplp.sqlOracle数据库不建议使用ansi sql, 有些时候ansi sql的执行计划比较难处理..
这样导致的结果就是a表中的每行数据的visit_ip都要经过运算才可以和后面的条件进行比较
加上你的表又大所以每行都作一次getAreaByIp(a.visit_ip)运算,时间可想而知。向你这种情况对a.visit_ip建立索引是无效的。优化方法:
1)考虑a表中是否有其它栏位可以作为条件过滤一些资料行,看你的情况似乎不适用
2)在a表中添加一个栏位adress,或者是添加一个栏位tip
在a表创建Trigger,通过to_number(getAreaByIp(:new.visit_ip))运算写入栏位tip
甚至可以直接得到地址写入address建议考虑第二种方法。这种做法是将运算分散到每次Insert中而不是在查询中才去运算。可以提高查询时间。
如果担心大批量插入速度受到影响,也可以写job定时运行更新a表中创建的tip或address栏位
我狂搜索,慢的原因有两个:
1:to_number(getAreaByIp(a.visit_ip)) 这个
2:是left join 左连接采用yqwd911(windy) 的方法2。再次感谢!