关于用了Hibernate之后如何进行SQL优化的问题

首先声明,我没有真正用过Hibernate做项目,只是有初浅了解而已,在这里提出这个问题,只是因为昨天在和公司的DBA探讨问题的时候有感而发,望大家多多拍砖。

我们公司做的是一个省级数据集中的大型系统,数据库采用的是Oracle,应用采用的是Struts1.2,数据库访问方面是采用直接构造、执行SQL的做法。昨天遇到这么个问题,发现一条sql语句执行非常慢,要好几分钟才能出结果。如下:
select b.unit 单位编号,
c.unit_name 单位名称,
c.address 地址,
c.link_man 联系人,
c.tel 电话,
c.remark 备注,
count(distinct b.cust_Id) 客户数,
count(a.user_id) 用户数
from
user a,
cust b,
unit c
where a.cust_id=b.cust_id
and b.unit=c.unit_login_name
and b.county_code='0801'
and c.unit_login_name='0801U04283'
group by b.unit,c.unit_name,c.address,c.link_man,c.tel,c.remark
order by c.unit_name

公司DBA做了一点点修改,执行时间马上缩短到两秒钟,修改过的语句如下:
select b.unit 单位编号,
c.unit_name 单位名称,
c.address 地址,
c.link_man 联系人,
c.tel 电话,
c.remark 备注,
count(distinct b.cust_Id) 客户数,
count(a.user_id) 用户数
from
user a,
cust b,
unit c
where a.cust_id=b.cust_id
and b.unit=c.unit_login_name
and b.county_code='0801'
and c.unit_login_name='0801U04283'
and a.county_code='0801'
and c.county_code='0801'

group by b.unit,c.unit_name,c.address,c.link_man,c.tel,c.remark
order by c.unit_name

只是加了两段看似没有实际意义的条件判断(加粗字体处,但在数据库优化上有意义,加了这两句就能利用到表的分区、索引)在性能上就得到了质的提高。

我想问的问题是:
1、采用Hibernate生成的sql语句是否能自动做这样的优化?这里采用的是自然连接,是不是Hibernate生成的sql语句会根据数据库的不同采用更好的优化过的语句?
2、如果Hibernate不能自动做这样的优化,是不是只能自己去用Hibernate的脚本语法去写类sql语句?或者有更好的解决方案?

[该贴被dd_macle于2007年06月29日 11:00修改过]
[该贴被dd_macle于2007年06月29日 11:01修改过]

你的思路反了,使用hibernate重点不室在于sql/hql语句的优化上
而是在于对象缓存和二级缓存上,在实际工程中,缓存的命中远远胜过对sql语句优化上。

to robertlyc:
"而是在于对象缓存和二级缓存上,在实际工程中,缓存的命中远远胜过对sql语句优化上",对那些变化不大的数据,用缓存是ok的,但对于我这边的省级集中,数据在飞快增加的应用,我觉得只能缓存那些配置信息、用户基本信息等基本不变的数据,业务数据怎么缓存呢?

想听听banq大哥的意见:)

关注中..............

缓存用在基本不变,而又经常访问的数据 没错
数据经常变的 但是命中率非常高,那使用缓存也能很大的提高效率

这些复杂的查询,使用HQL与方言效率差别很大的,你可以使用SQLQUERY或者存储过程来实现。HIBERNATE只是提供了那么一层封装,让你的业务逻辑与复杂数据库操作分开而已。一个经典的系统,应该是拿多种技术拼凑而成的。每个技术都有他的优点缺点,只当这个技术在时间,成本,质量三者权衡后 取最大值时才使用.

不好意思,这段时间比较忙,一直没来看,gougou3250兄所言极是,一个好的有一定规模的系统,为了在开发效率、运行效率等多方面获得平衡,一般来说都不会只采用单一的某种技术,而是根据实际情况,在不同的场合运用多种技术来实现。

比如:对于哪些经常要执行的批量插入、查询的操作,采用存储过程就能获得比较好的效率,而在大多数普通的操作,采用Hibernate本身的ORM即可

使用Hibernate,就要依据对象法则来分析设计系统,这有赖于架构水平(在这个时期,架构师薪水最高)。

你现在的系统实际是面向数据库系统,这就有赖于DBA水平(在这个时期,DBA薪水最高)。

楼上已经说了,使用缓存,但是前提必须是对象缓存,而不是分散的数据缓存。因为你使用了Hibernate,实际就走上了依靠对象方式提高性能的另外一条之路;这条路和你数据库性能提升方式是不一样的思路。

现在,你试图两个思路都用,这两个是矛盾的,所以很显然不现实,这也是很多人反映Hibernate并“不好用”原因所在。

Hibernate封装了SQL,那么你就只能依靠Hibernate手册提供的优化技巧力所能及的进行优化。

但是不要让业务逻辑触碰到SQL语句,或者与SQL发生耦合,这是原则。

你希望通过存储过程等语句,那么也要依据上述原则。所有这些前提是:如果你想走OO路线,想让你的程序变得更好的可维护性和可拓展性。