2007-07-25

因无索引导致的性能问题

测试那边说, 页面打开很慢, 自己跑去试了下, 果然, 一个搜索结果页面, 大概要30s~60s, 查看了下代码, 发现是段hql执行问题, 就抽取出来单独测试, 这个查询类似这样的结构:
select count(*) from a, b where a.bid = b.bid;

其中a表中的bid是b表的id外键. 每个表大概有7k条记录.这个查询每次都耗时30s, 后来把a表中的bid字段建立个属性, 速度就快多了, 大概是300ms~1s.

以前一直没觉得索引有这么神奇的效果.....

--
It's Hard to Define, But I Know it When I See it…

2007-07-24

接口参数类型

之前写过一个接口, 目的是更新FriendLink对象到数据库.形式如下:

update(FriendLink link);

接口的实现是这么写的:
update(FriendLink link){
    dao.update(link);
}

后来, 发现有弊病在: 这个接口依赖这样的事实: link已经存在于数据库中 .这样很容易产生潜在的不安全性, 外部的任何程序都可以随意构造一个FriendLink实例(而不是从数据库中取然后稍加修改而成的), 然后传入到这个接口, 然后产生异常. 还有个问题就是, 它限制了访问媒介为java对象(须先构造出FriendLink对象来, 才能访问到这个接口), 不利于其它形式的访问(如webServices, REST等---虽然可以, 但是须对FriendLink中accessor信息了然于胸). 所以应修改如下:

update(long friendLinkId);

传入基本类型(long), 声明说会对这个(id为friendLinkId的FriendLInk)作更新, 这样, link已经存在于数据库中  这样的谓词是由接口内部来判断处理的. 对于其它形式的访问, 基本类型都是被支持的. 至于update的信息, 可以以参数形式, 或函数名形式展现, 如下:
update(long frindLinkId, Date accessDate); ①

updateAccessDate(long friendLinkId);②

象②这样的只传入id的接口, 依赖于"执行更新所需信息可以从接口上下文得到", 比如当前时间等.所以应用面比较狭窄, 不知道具体应该怎么处理(map参数?) :( (还是动态语言比较好, 象js的arguments参数很灵活)

--
It's Hard to Define, But I Know it When I See it…

date 与 timestamp 类型

用一句话说就是:
timestamp比date精确.
用date只能搞到日期, 时间得不到, 所以在sql里面进行alter时, 只有timestamp=>date的转换, 如果想执行相反的转换会报异常.

如果用hibernate进行映射, 一般来说是 java.util.Date=>timestamp.否则, 标志性的异常信息是batch update exception (不过有个有趣的现象是, 如果你设置hibernate.jdbc.batch_size 为0的话, 就能顺利执行, 应该是hibernate的bug)
P.S. 如果是用xdoclet映射字段, 不要这么写:
@hibernate.property column="createDate" type="date" 
把type写全:java.util.Date. 否则会引来不必要的麻烦: hibernate会把它错当成java.sql.Date :(

--
It's Hard to Define, But I Know it When I See it…