mysql 查询优化
不说话,先贴代码
public PageResult<BoTmcRaw> getLargeList(BaseCondition baseCondition) { PageResult<BoTmcRaw> result=new PageResult<BoTmcRaw>(); Session session = this.getSessionFactory().getCurrentSession(); StringBuilder conditionStr=new StringBuilder(); conditionStr.append(""); if(baseCondition.getParamSql()!=null)conditionStr.append(baseCondition.getParamSql()); conditionStr.append(" order by "+baseCondition.getOrder()+" "+baseCondition.getSort()); conditionStr.append(" limit "); conditionStr.append((Integer.parseInt(baseCondition .getPage()) - 1) * Integer.parseInt(baseCondition.getRows())); conditionStr.append(","); conditionStr.append(Integer.parseInt(baseCondition.getRows())); String sql="select id from Bo_Tmc_Raw where 1=1 "+conditionStr.toString(); SQLQuery q = session.createSQLQuery(sql); q.addScalar("id",Hibernate.LONG); List<Long> ids = q.list(); String idstr=""; for(Long item:ids){ idstr=idstr+item+","; } if(ids.size()!=0)idstr=idstr.substring(0,idstr.length()-1); sql="from BoTmcRaw where id in("+idstr+")"; Query ql = session.createQuery(sql); result.setList(ql.list()); SQLQuery qc = session.createSQLQuery("select count(id) from bo_tmc_raw where 1=1 "+baseCondition.getParamSql()); result.setCount(((BigInteger)qc.uniqueResult()).intValue()); return result; }
众所周知啊,mysql是轻量级的数据库,有很多功能是他不具备的。造句挺难的,别嫌我啰嗦,这个查询分页,其实很早我就注意到了,只是一直没有机会搞。
mysql是有查询分页功能的,limit这个关键字有人不知道,这个一点也不奇怪,但是当你认识他的时候,幸运的家伙会有好心人告诉你,这个不是真正的分页,mysql服务器还是会把所有的条目都遍历一遍,反正意思就是说,这个limit算法是有问题的,到底是不是这个好心人说的那样,我现在却有点怀疑了。
我们现在再来看看这个,
select * from ooo where id>=(select id from ooo limit 4523,1) limit 0,10;
写完sql加;是个好习惯。
但是。。算了;
这是我刚刚学习的一个语法,他的意思是说,limit算法的速度,取决于第一个参数的大小。第一个数,也就是开始位置越大,这个查询的时间就越长。这一点我刚刚证实是正确的,不做其他讨论。
依据这个语法,我们可以做出比直接使用limit更高效的查询,但是在实际应用中,这个直接拿来用很不好用。所以,这个只能做一个概念模型。
其实原理都是一样的,id作为索引,其查询效率非常高,用id做分页,然后分页得到的id用来做少量的全字段查询。我们要考虑的是,如果再加入排序,顺序倒序,其他字段排序,为什么一定要用大于号?sql里面现成的in关键字怎么不用?不要跟我说什么效率,你一页能显示多少数据?在一页数据中这个效率问题是可以忽略不计的。无论如何,比你手动10几20次查询快的多。也有人说用exists,这个语法只能用来关联查询,in是可以拼字符串的,显然比起两个表的关联查询,还是分开查比较好。
目前这个结果还算不错,大约70万条数据左右吧,第一页是瞬间就出来了,然而最后一页还是花了不少时间,可能用where比较好吧。别忘了加索引!索引!索引!重要的事情说三遍!加在id上就行。