要性能,还是要设计?

今天到新公司上班,写了一段非常简单的代码,负责把数据库一个表的log逐条显示出来,我写了一个XXLog类,用一个静态方法得到一个Iterator,里面容纳查询到的XXLog:
public class XXLog{
String logname;
Date logtime;
...
public static Iterator getAllLogs(Date d,int start,int num){
...
while(rs.next()){
XXLog alog = new XXLog();
alog.setLogname(rs.getString(1));
...
}
}
}
这种设计有无问题?
我也发现里面new了许多XXLog对象,对性能影响是很大的
于是采用同事建议
public class XXLog{
public Hashmap[] getAllLogs(){
...
while(rs.next()){
Hashmap.put("column1",rs.getString(1));
Hashmap.put("column2",rs.getString(2));
...

}
return Hashmap;
}
将数据保存到一个hashtable数组里面返回给调用端
这样避免了new许多实体对象
不过感觉好像不是面向对象的设计思路
可是性能肯定会好许多
。。。
还有要提到的就是jive的相关设计
jive取多个帖子的方法是这样:
查询到需要的帖子的id保存到一个Iterator里面
然后继承Iterator的next方法,在next方法里面
按照id去得到相关的帖子
这样是否加大了查许的频度?
比如要取得20条帖子,查到20个id后,再
根据每个id去select20次帖子出来
总共检索数据库21次,还不如用hashtable容纳结果
一次传过来

使用Hashtable传送数据是不可取做法,不利于以后扩展和重用。
提高性能不是使用这种低级办法,如果是这样,还是那句话,使用汇编好了。

你原来的方案虽然重视俩OO,但是没有更进一步从性能上设计考虑。

而Jive的Iterator模式使用提供了借鉴,按照需要取出记录,一次性只取出一个页面的数据库记录,当然之前通过将所有ID都查询出来,这种查询是很快地,在EJB中或O/R mapping技术中,表面上代码只有一句,底层机制还是可能实现多次查询的,这已经是Java为提高OO设计采取的共同默认的办法。

再解释一下Jive的Iterator原理,Jive根据客户端查询语句,将所有满足条件的ID集合出来,比如有200个,但是每页只显示20个,那么就从数据库查询20条记录,并封装成对象如JiveMessage传送到表现层,表现层使用iterator遍历这个20条记录数据对象集合,输出到浏览器。

Java是重视设计的,所以才牺牲一些性能,如果你确实需要性能,那么可以象使用过程语言一样使用Java,到处是长方法,到处是基本数据类型,HashTable满天飞,但是这样做的后果是,当系统复杂到一定程度,开发者自己就会崩溃,要么离职,要么升官。

我一直认为,既然你选择Java,那么就意味着你走上一条重视设计的道路,千万别叶公好龙。

这两种设计全都不对,其实不关性能还是设计的选择问题,你不过是在两种不同类型的错误的设计中选择一个罢了。

那么banq你认为怎样才能提升他的第一个程序的性能
我也是这样做的
我认为似乎没有什么更好一点的办法
能不能给点idea

晕,除了这两种方法我还不知道有其他的哪???

这两种设计全都不对,

要设计!

如果没有对性能的苛刻要求, 绝对设计至上(不是设计模式)
想想你以后维护这些程序的时候, 看到的是一堆乱七八糟的东西, 看的云里雾里你就知道多惨了.

jsp+bean是追求速度的典范. asp.net的服务器端控件则完全是追求设计, 开发者可以在IDE里面象写vb一样点一下就生成各种事件. 代码量大大减少.

现在硬件越来越廉价, 性能换设计是方向, 不要在性能上费劲了.

这个案例的方案就目前提供的信息看来,我认为解决方案,是采取Transfer Object模式,也就是VO模式,或者说是POJO吧,后者我叫不惯,可能理解不准确。

就是将一列列数据打包成一个对象

|col1 | col2 |col3 |col4
------------------------
|col1 | col2 |col3 |col4
------------------------
|col1 | col2 |col3 |col4

每一行打包成一个对象,所有行加入一个List中,然后返回客户端。
这是一般标准的使用办法。

当然,如果数据量大,如有100个,客户端只能每行显示20个,那么上面的List中就包含20个对象返回客户端。

以页面向后查询时,可参考Jive的Iterator模式和Petstore的Page模式。

这是典型的inner-tier data transfer pattern的应用.
参考EJB design pattern中的data transfer object, domain data transfer object, 或custom data transfer object pattern.

Using HashMaps for genericising a DTO layers comes with some very pyrotechnic advantages as well as disadvantages, Most of developers find themselves most confortable using proper data transfer objects, they have well-understood usage patterns, and it isvery difficult for client side developers to make mistakes when using them, data transfer HashMaps are adouble-edged sword that solve many maintenance problems but also add others, The design on which methos to use is a judgment that should be made based on your own project needs

data thansfer RowSet is Using RowSets for marshalling raw relational data directly from a Result in the EJB tier to the client tier.

in EJB, 有data thansfer object, data thansfer HashMap, data thansfer RowSet.

in .net, 有typed dataset, 它集成了object 和 Rowset, 这是我看到的最好办法.

在commons项目中,有一个包,可以把resultset转成对象。

一个函数而已。

Log 这个东西的数据量是很大的。
我看你的方法里有 start 偏移量与 num 总量。这说明你的方法更倾向于做 Pagination 这种应用。

如果你的 sql 语句就是返回显示所需的条数,如 20 条,而且这个 Log 的集合也不需要在网络上传输,那么你第一个实现的用法没有什么大的问题。我个人认为这样的性能损失不会很大。客户可以接受。(只要客户可以接受,就没有必要做过多的优化,因为过多的优化需要一种投入,而这样的投入并不能带来额外的效益,所以最好不要做这样的事)

其实,我更偏向于使用存贮过程来做 Data 层的事,一个 SQL 语句,一次数据传输就可以解决。

多谢各位精辟的讨论,对这个问题我已经比较了解
我现在发现即使采用Hashtable传递数据,
也必须new相应数量的Hashtable对象,而采用Hashtable
省略了实体对象的设计,但在取Hashtable数据的时候要有一个查询代价

现在问题是采用jive的设计问题:
客户端要得到20条数据,则必须查询21次
第一次查询得到开始和结束的id
然后遍历的过程中对每个id做一次查询


害怕创建太多对象?
可以用flyweight

你可以变通一下嘛~~

比如说,第一次获得一个 id 的结果集,然后根据要显示的页面信息计算出需要显示的 id 字集,如(id1,id2,...,idn)
然后在 SQL 语句时直接用 SELECT <fields> FROM <table|view> WHERE id IN (id1,id2,...,idn)

这样就是两个 SQL 语句嘛~~

如果你对 SQL 的存贮过程熟悉,完全可以用 Store Procedure 来做嘛一个 SQL 语句就完成了