我的评论

共6页: 上一页 1 2 3 4 5 6 下一页 
re: 软件开发#前途 久城 2007-09-15 18:44  
我也在做外包,的确不需要很多的技术含量。相对技术来说,外包更多的是侧重软件工程各方面的能力,这需要经验。

黑蝙蝠,好久不见你出没了啊。
re: JAVA元数据注释初探 久城 2007-09-15 11:20  
JAVA元数据的应用挺有意思的,一直想学习一下,却一直没有好好学习过。

我见过的,只有Javadoc是元数据比较常见的应用了哈哈。
学习一下。谢谢楼主。
realsmy@gmail.com
很感兴趣,不知道楼主能介绍下你的开发环境和工具吗?~很想借鉴一下。
re: 开场白 久城 2007-09-12 12:53  
代DUDU欢迎你!~
re: JAVA中的时间操作 久城 2007-09-12 08:00  
关于时间的运算,用Calendar或者其子类GregorianCalendar也许更好一些。
re: 索引初步接触 久城 2007-09-11 11:31  
在网上查到的传阅比较广泛的一个实例,感觉对理解索引的应用有很大的帮助。

具体出处不详。

如何让你的SQL运行得更快

---- 人们在使用SQL时往往会陷入一个误区,即太关注于所得的结果是否正确,而忽略了不同的实现方法之间可能存在的性能差异,这种性能差异在大型的或是复杂的数据库环境中(如联机事务处理OLTP或决策支持系统DSS)中表现得尤为明显。笔者在工作实践中发现,不良的SQL往往来自于不恰当的索引设计、不充份的连接条件和不可优化的where子句。在对它们进行适当的优化后,其运行速度有了明显地提高!下面我将从这三个方面分别进行总结:
---- 为了更直观地说明问题,所有实例中的SQL运行时间均经过测试,不超过1秒的均表示为(< 1秒)。
---- 测试环境--
---- 主机:HP LH II
---- 主频:330MHZ
---- 内存:128兆
---- 操作系统:Operserver5.0.4
---- 数据库:Sybase11.0.3


一、不合理的索引设计

----例:表record有620000行,试看在不同的索引下,下面几个 SQL的运行情况:
---- 1.在date上建有一非个群集索引
select count(*) from record where date >
'19991201' and date < '19991214'and amount >
2000 (25秒)
select date,sum(amount) from record group by date
(55秒)
select count(*) from record where date >
'19990901' and place in ('BJ','SH') (27秒)
---- 分析:
----date上有大量的重复值,在非群集索引下,数据在物理上随机存放在数据页上,在范围查找时,必须执行一次表扫描才能找到这一范围内的全部行。

---- 2.在date上的一个群集索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000 (14秒)
select date,sum(amount) from record group by date
(28秒)
select count(*) from record where date >
'19990901' and place in ('BJ','SH')(14秒)
---- 分析:
---- 在群集索引下,数据在物理上按顺序在数据页上,重复值也排列在一起,因而在范围查找时,可以先找到这个范围的起末点,且只在这个范围内扫描数据页,避免了大范 围扫描,提高了查询速度。

---- 3.在place,date,amount上的组合索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000 (26秒)
select date,sum(amount) from record group by date
(27秒)
select count(*) from record where date >
'19990901' and place in ('BJ, 'SH')(< 1秒)
---- 分析:
---- 这是一个不很合理的组合索引,因为它的前导列是place,第一和第二条SQL没有引用place,因此也没有利用上索引;第三个SQL使用了place,且引用的所有列都包含在组合索引中,形成了索引覆盖,所以它的速度是非常快的。

---- 4.在date,place,amount上的组合索引
select count(*) from record where date >
'19991201' and date < '19991214' and amount >
2000(< 1秒)
select date,sum(amount) from record group by date
(11秒)
select count(*) from record where date >
'19990901' and place in ('BJ','SH')(< 1秒)
---- 分析:
---- 这是一个合理的组合索引。它将date作为前导列,使每个SQL都可以利用索引,并且在第一和第三个SQL中形成了索引覆盖,因而性能达到了最优。

---- 5.总结:
---- 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的;合理的索引设计要建立在对各种查询的分析和预测上。一般来说:
---- ①.有大量重复值、且经常有范围查询
(between, >,< ,>=,< =)和order by
、group by发生的列,可考虑建立群集索引;
---- ②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引;
---- ③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。


二、不充份的连接条件:

---- 例:表card有7896行,在card_no上有一个非聚集索引,表account有191122行,在account_no上有一个非聚集索引,试看在不同的表连接条件下,两个SQL的执行情况:

select sum(a.amount) from account a,
card b where a.card_no = b.card_no(20秒)
---- 将SQL改为:
select sum(a.amount) from account a,
card b where a.card_no = b.card_no and a.
account_no=b.account_no(< 1秒)
---- 分析:
---- 在第一个连接条件下,最佳查询方案是将account作外层表,card作内层表,利用card上的索引,其I/O次数可由以下公式估算为:
---- 外层表account上的22541页+(外层表account的191122行*内层表card上对应外层表第一行所要查找的3页)=595907次I/O
---- 在第二个连接条件下,最佳查询方案是将card作外层表,account作内层表,利用account上的索引,其I/O次数可由以下公式估算为:
---- 外层表card上的1944页+(外层表card的7896行*内层表account上对应外层表每一行所要查找的4页)= 33528次I/O
---- 可见,只有充份的连接条件,真正的最佳方案才会被执行。
---- 总结:
---- 1.多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表;内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案。
---- 2.查看执行方案的方法-- 用set showplanon,打开showplan选项,就可以看到连接顺序、使用何种索引的信息;想看更详细的信息,需用sa角色执行dbcc(3604,310,302)。


三、不可优化的where子句

---- 1.例:下列SQL条件语句中的列都建有恰当的索引,但执行速度却非常慢:
select * from record where
substring(card_no,1,4)='5378'(13秒)
select * from record where
amount/30< 1000(11秒)
select * from record where
convert(char(10),date,112)='19991201'(10秒)
---- 分析:
---- where子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表搜索,因此将SQL重写成下面这样:
select * from record where card_no like
'5378%'(< 1秒)
select * from record where amount
< 1000*30(< 1秒)
select * from record where date= '1999/12/01'
(< 1秒)
---- 你会发现SQL明显快起来!

---- 2.例:表stuff有200000行,id_no上有非群集索引,请看下面这个SQL:
select count(*) from stuff where id_no in('0','1')
(23秒)
---- 分析:
---- where条件中的'in'在逻辑上相当于'or',所以语法分析器会将in ('0','1')转化为id_no ='0' or id_no='1'来执行。我们期望它会根据每个or子句分别查找,再将结果相加,这样可以利用id_no上的索引;但实际上(根据showplan),它却采用了"OR策略",即先取出满足每个or子句的行,存入临时数据库的工作表中,再建立唯一索引以去掉重复行,最后从这个临时表中计算结果。因此,实际过程没有利用id_no上索引,并且完成时间还要受tempdb数据库性能的影响。
---- 实践证明,表的行数越多,工作表的性能就越差,当stuff有620000行时,执行时间竟达到220秒!还不如将or子句分开:
select count(*) from stuff where id_no='0'
select count(*) from stuff where id_no='1'
---- 得到两个结果,再作一次加法合算。因为每句都使用了索引,执行时间只有3秒,在620000行下,时间也只有4秒。或者,用更好的方法,写一个简单的存储过程:
create proc count_stuff as
declare @a int
declare @b int
declare @c int
declare @d char(10)
begin
select @a=count(*) from stuff where id_no='0'
select @b=count(*) from stuff where id_no='1'
end
select @c=@a+@b
select @d=convert(char(10),@c)
print @d

---- 直接算出结果,执行时间同上面一样快!
---- 总结:
---- 可见,所谓优化即where子句利用了索引,不可优化即发生了表扫描或额外开销。

---- 1.任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。
---- 2.in、or子句常会使用工作表,使索引失效;如果不产生大量重复值,可以考虑把子句拆开;拆开的子句中应该包含索引。
---- 3.要善于使用存储过程,它使SQL变得更加灵活和高效。
---- 从以上这些例子可以看出,SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。

1 逻辑数据库和表的设计
  数据库的逻辑设计、包括表与表之间的关系是优化关系型数据库性能的核心。一个好的逻辑数据库设计可以为优化数据库和应用程序打下良好的基础。

  标准化的数据库逻辑设计包括用多的、有相互关系的窄表来代替很多列的长数据表。下面是一些使用标准化表的一些好处。

A:由于表窄,因此可以使排序和建立索引更为迅速
B:由于多表,所以多镞的索引成为可能
C:更窄更紧凑的索引
D:每个表中可以有少一些的索引,因此可以提高insert update delete等的速度,因为这些操作在索引多的情况下会对系统性能产生很大的影响
E:更少的空值和更少的多余值,增加了数据库的紧凑性由于标准化,所以会增加了在获取数据时引用表的数目和其间的连接关系的复杂性。太多的表和复杂的连接关系会降低服务器的性能,因此在这两者之间需要综合考虑。
  定义具有相关关系的主键和外来键时应该注意的事项主要是:用于连接多表的主键和参考的键要有相同的数据类型。

  2 索引的设计
A:尽量避免表扫描
检查你的查询语句的where子句,因为这是优化器重要关注的地方。包含在where里面的每一列(column)都是可能的侯选索引,为能达到最优的性能,考虑在下面给出的例子:对于在where子句中给出了column1这个列。
下面的两个条件可以提高索引的优化查询性能!
第一:在表中的column1列上有一个单索引
第二:在表中有多索引,但是column1是第一个索引的列
避免定义多索引而column1是第二个或后面的索引,这样的索引不能优化服务器性能
例如:下面的例子用了pubs数据库。
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = ’White’
按下面几个列上建立的索引将会是对优化器有用的索引
?au_lname
?au_lname, au_fname
而在下面几个列上建立的索引将不会对优化器起到好的作用
?au_address
?au_fname, au_lname
考虑使用窄的索引在一个或两个列上,窄索引比多索引和复合索引更能有效。用窄的索引,在每一页上将会有更多的行和更少的索引级别(相对与多索引和复合索引而言),这将推进系统性能。
对于多列索引,SQL Server维持一个在所有列的索引上的密度统计(用于联合)和在第一个索引上的histogram(柱状图)统计。根据统计结果,如果在复合索引上的第一个索引很少被选择使用,那么优化器对很多查询请求将不会使用索引。
有用的索引会提高select语句的性能,包括insert,uodate,delete。
但是,由于改变一个表的内容,将会影响索引。每一个insert,update,delete语句将会使性能下降一些。实验表明,不要在一个单表上用大量的索引,不要在共享的列上(指在多表中用了参考约束)使用重叠的索引。
在某一列上检查唯一的数据的个数,比较它与表中数据的行数做一个比较。这就是数据的选择性,这比较结果将会帮助你决定是否将某一列作为侯选的索引列,如果需要,建哪一种索引。你可以用下面的查询语句返回某一列的不同值的数目。
select count(distinct cloumn_name) from table_name
假设column_name是一个10000行的表,则看column_name返回值来决定是否应该使用,及应该使用什么索引。
Unique values Index

5000 Nonclustered index
20 Clustered index
3 No index

镞索引和非镞索引的选择

<1:>镞索引是行的物理顺序和索引的顺序是一致的。页级,低层等索引的各个级别上都包含实际的数据页。一个表只能是有一个镞索引。由于update,delete语句要求相对多一些的读操作,因此镞索引常常能加速这样的操作。在至少有一个索引的表中,你应该有一个镞索引。
在下面的几个情况下,你可以考虑用镞索引:
例如: 某列包括的不同值的个数是有限的(但是不是极少的)
顾客表的州名列有50个左右的不同州名的缩写值,可以使用镞索引。
例如: 对返回一定范围内值的列可以使用镞索引,比如用between,>,>=,<,<=等等来对列进行操作的列上。
select * from sales where ord_date between ’5/1/93’ and ’6/1/93’
例如: 对查询时返回大量结果的列可以使用镞索引。
SELECT * FROM phonebook WHERE last_name = ’Smith’

当有大量的行正在被插入表中时,要避免在本表一个自然增长(例如,identity列)的列上建立镞索引。如果你建立了镞的索引,那么insert的性能就会大大降低。因为每一个插入的行必须到表的最后,表的最后一个数据页。
当一个数据正在被插入(这时这个数据页是被锁定的),所有的其他插入行必须等待直到当前的插入已经结束。
一个索引的叶级页中包括实际的数据页,并且在硬盘上的数据页的次序是跟镞索引的逻辑次序一样的。

<2:>一个非镞的索引就是行的物理次序与索引的次序是不同的。一个非镞索引的叶级包含了指向行数据页的指针。
在一个表中可以有多个非镞索引,你可以在以下几个情况下考虑使用非镞索引。
在有很多不同值的列上可以考虑使用非镞索引
例如:一个part_id列在一个part表中
select * from employee where emp_id = ’pcm9809f’
查询语句中用order by 子句的列上可以考虑使用镞索引

3 查询语句的设计

SQL Server优化器通过分析查询语句,自动对查询进行优化并决定最有效的执行方案。优化器分析查询语句来决定那个子句可以被优化,并针对可以被优化查询的子句来选择有用的索引。最后优化器比较所有可能的执行方案并选择最有效的一个方案出来。
在执行一个查询时,用一个where子句来限制必须处理的行数,除非完全需要,否则应该避免在一个表中无限制地读并处理所有的行。
例如下面的例子,
select qty from sales where stor_id=7131
是很有效的比下面这个无限制的查询
select qty from sales
避免给客户的最后数据选择返回大量的结果集。允许SQL Server运行满足它目的的函数限制结果集的大小是更有效的。
这能减少网络I/O并能提高多用户的相关并发时的应用程序性能。因为优化器关注的焦点就是where子句的查询,以利用有用的索引。在表中的每一个索引都可能成为包括在where子句中的侯选索引。为了最好的性能可以遵照下面的用于一个给定列column1的索引。
第一:在表中的column1列上有一个单索引
第二:在表中有多索引,但是column1是第一个索引的列不要在where子句中使用没有column1列索引的查询语句,并避免在where子句用一个多索引的非第一个索引的索引。
这时多索引是没有用的。
For example, given a multicolumn index on the au_lname, au_fname columns of the authors table in
the pubs database,
下面这个query语句利用了au_lname上的索引
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = ’White’
AND au_fname = ’Johnson’
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = ’White’
下面这个查询没有利用索引,因为他使用了多索引的非第一个索引的索引
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_fname = ’Johnson’

re: Dom4j 简单读写XML文件的例子 久城 2007-09-10 15:04  
网站中,一般什么样的数据放在XML文件中,而不是放到应用数据库中?为什么?放到XML中,一般都是结合什么样的技术去应用?

看了两个帖子,正好是我现在想研究的内容,忍不住问了两个即比较低级的问题,还请见谅。:)
问一个比较低级的问题,网站中的很多动态增加的HTML页面就是这样作成的吗?
比如csdn上每天的一些动态新闻的网页,都是一个HTML页面,目录结构可能是www.csdn.net/news/20070910/0001.html,这样的页面都是如何生成的?是不是也是用一个专门生成HTML页面的类来自动生成啊?
迷惑中,还请指教。
re: 50本书总结的50句话(转载) 久城 2007-09-10 08:16  
抑郁啊...基本上都没看过...
re: 北京--看不见的城市 久城 2007-09-08 12:08  
从头看到尾...

写的挺有感觉...
re: 过河卒 久城 2007-09-04 17:30  
名字不错,支持个。....
re: 大四JAVA实验(一) 久城 2007-09-03 21:04  
??....??
从头看到尾,有所收获。
re: 我的blog访问者分析 久城 2007-08-31 10:40  
哈哈,太有想法了啊。

刚刚试了下,挺有意思。GOOGLE就是牛啊。
re: 我的blog访问者分析 久城 2007-08-31 10:27  
-.-!.........博主........就是草儿你啊。....

现在只有显示结果,如果BZ能再谈谈对这一结果的看法就好了。:)
re: 我的blog访问者分析 久城 2007-08-31 09:14  
想听听BZ对此的评价或分析。
re: 新功能发布 久城 2007-08-31 08:42  
维护签名页面中的编辑器中的‘维护签名’按钮,是不是可以去掉了?
re: 新功能发布 久城 2007-08-31 08:24  
哈哈,我刚帮你发布完。看来我得把我的删了。
用JS实现的?我JS盲。看起来挺有意思。

也可以写成一个批处理文件。
native2ascii a.properties b.properties
re: JAVA截屏程序 久城 2007-08-30 16:40  
不会,学习下。
re: 转 侯捷谈Java反射机制 久城 2007-08-29 14:30  
小小UP下。
五个月前,做JAVA CLASS LOADING的毕设,看过这篇文章,当时很费解侯老先生到底在研究什么。
今天,想尝试研究一下JAVA类的序列化,又看了一遍这篇文章,收益良多。
re: 读J道一经典帖有感 久城 2007-08-25 07:55  
原帖网址:http://www.jdon.com/jivejdon/thread/31338.html
在Jdon的首页上有个标题叫“j2se基础的重要性”,就是那个帖子。
2007年8月11日,在屋睡了一天的觉。
2007年8月12日,沈阳下了一天的雨。
re: 这几天存储过程应用的点滴 久城 2007-08-15 15:20  
......
太受打击了...
re: 关于BLOGJAVA界面CSS的疑问 久城 2007-08-15 10:01  
@Hmilyld
very thanks.:)
看过你baidu的blog.:)
对于blogjava的意见,写到http://www.blogjava.net/dudu/这里去。DUDU会很感谢你的。
re: 写得蛮好的linux学习笔记 久城 2007-08-15 08:17  
估计过阵子就会用上,先收藏个。
re: 发布一个新Skin 久城 2007-08-15 08:11  
这东西,不怕多,多多益善,哈哈。
re: 日記3 久城 2007-08-14 20:00  
太强了啊,学习。
re: 基于TCP的多人聊天小程序 久城 2007-05-25 13:08  
@L
:)工作的人和没工作的人考虑的事情就是不一样啊!我只考虑了实现通信,却没有想过程序的性能如何。好多想法还太单纯。
..恩,要看的东西还有好多。谢谢指点。
re: 论兔子如何吃掉狼 久城 2007-05-25 10:11  
这个学生很聪明,能够准确巧妙的运用导师的能力。
re: 基于TCP的多人聊天小程序 久城 2007-05-25 09:39  
原来如此。我昨天用Applet尝试了半天,始终连接不上服务端。一直不知道是哪里出错了。呵呵。
我的理想也是从事教育...因为赚钱...为什么赚钱呢?

呵呵,事实摆在眼前,其实大家人人都心知肚明。
re: 论剑归来(一) 久城 2007-05-22 17:11  
UP。我在一个遥远的小山沟里望着你们前进...
re: curl 久城 2007-05-22 17:06  
小さい かわいい、 がんばって ください!
re: java元数据的学习 久城 2007-05-22 16:40  
看完了,试了下。终于有了些思路。谢谢BZ。
只是有些疑惑,我们什么时候能用到annotation呢?
期待......
2006年年度最佳雇主的单位?阎罗大哥是哪里的?
re: 生存的压力和生命的尊严 久城 2007-05-17 10:30  
加油!
呵呵!......
re: Google Server Error截屏留念 久城 2007-05-14 20:59  
别怕我伤心---我喜欢听!
@刘甘泉
了解了!^.^!
@刘甘泉
多谢指教。在网上看到一些文章也是提醒要注意修改时的操作。
至于修改什么还不是很清楚。
我想,在应用深度clone的时候,需要重写Object类中的clone方法,对于基本类型就不用考虑了,对于非基本类型,需要手动的进行“复制”。大家所说的“会引起问题”是出自这里吧?这个“复制”如果也是一个clone,就需要考虑这个非基本类型对象是否允许被clone,这个clone操作是否也是深度clone等问题。
象StringBuffer这样的,不可修改的类。就需要手动的“COPY IT!”
还有一些就需要用到迭代方法,来迭代执行clone方法,达到N深度clone的效果。
这些我还没有深入的研究。感觉实践中用的机会很少。
@网路冷眼@BlogJava
哦!多谢指教。还真没注意这个地方。一直以为是Group of Four呢!一叫“四人帮”总是让我想起中国的那四个人...
共6页: 上一页 1 2 3 4 5 6 下一页 

Copyright © 久城