weitom1982

向各位技术前辈学习,学习再学习.
posts - 299, comments - 79, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

怎么管理你自己?杜拉克说,你要问自己五个问题。关键在于,回答问题后要采取相应的行动。
Lan Liu


  "认识你自己",两千多年前,古希腊的哲人说。古希腊人比较形而上,没有说清楚怎么认识你自己。"管理你自己",一九九九年,管理大师杜拉克发表文章说。杜拉克深刻而务实,终于向经理人说清楚了怎么认识你自己,而且把"认识"上升到了"管理"的高度。怎么管理你自己?杜拉克说,你要问自己五个问题。

  第一个问题是:我的长处是什么?很少人真正知道正确答案。你应该向周围的人寻求反馈并加以分析,发现自己真正的长处,然后努力完善自己的长处。同时,找到那些妨碍了自己发挥长处的地方(比如轻视自己专业领域之外的某种重要的技能、或者在人际交往中缺乏应有的礼貌),把它们改掉。

  第二个问题是:我做事的方式是什么?就像人的长处各有不同,做事方式也各有不同。比如你是"读者"(reader)还是"听者"(listener)?"读者"喜欢看书面资料,"听者"习惯听口头汇报。又比如,你用什么方式学习?最常见的是"听"和"读",但是也有许多人的主要学习方式是"写"或"说"。

  在做事方式这个大问题下,要问的小问题还很多。比如,你是擅长团队合作,还是习惯单打独斗?你是擅长做一把手,还是习惯做副手?你是当决策者还是军师?你是在高压之下越战越勇,还是在和平有序的环境下才能出色发挥?你是在大公司还是在小企业更能取得绩效?关键不在于回答这些问题,而在于回答问题后并采取相应的行动。

  第三个问题是:我的价值观是什么?人和企业都有自己的经营价值观,如果二者冲突,你就难以发挥绩效。比如,如果你信仰内部培养人才而企业喜欢空降外援,你追求长期业绩而企业追求短期结果,你倡导突破性创新而企业愿意持续改善,就是价值观的冲突,而不是谁对谁错的问题。

  回答前三个问题后,你才能回答第四个问题:我该去哪里工作?或者,你至少知道你不该去哪里工作。知道该对什么样的工作机会说不,知道自己将以怎样的方式做一项新工作,并要求相应的预期和配合。

  这时该回答第五个问题了:我该贡献什么?要考虑到三方面的因素:一是形势的要求,二是基于自己的长处、做事方式和价值观,怎样能做出最大贡献,三是什么样的结果影响深远。

  认识你自己之后,要付诸相应的行动,才是管理你自己。

posted @ 2006-03-31 12:48 高山流水 阅读(87) | 评论 (0)编辑 收藏

导致消极情绪的谈话无处不在。把消极变为积极才能增加业绩。
Alexander Hiam 


  工作会议结束后,一些员工一边收拾东西,一边闲聊。你不经意地听到他们的对话,开始琢磨他们言谈中表现出来的情绪。

  其中一个员工说:"你是斗不过人事部的,他们总会找些理由让你的医疗费报不了。"另一个说:"是吗?我不知道这回事,我还没有报过医疗费呢。"

  你摇了摇头,走开了。你很遗憾听到公司的老员工把一种消极的态度传递给了新员工。根据你的经验,报销医疗费本身是件很复杂的事,人事部并没有故意找茬使事情难办。事实上,起因通常是员工自己没能提供足够的信息,或者没有及时交上报销单据才使事情变得麻烦的,员工却把自己的错误归咎到人事部头上。那么,你该怎么做呢?这只是个闲聊,与你无关,是吗?

  员工的消极对话会影响士气和工作态度,一旦这种消极的情绪传播开来,将使你激发员工积极性的努力功亏一篑,所以每个经理人都应该认真对待这个问题。

  在上述例子中那个发牢骚的员工觉得自己是"受害者",并把这种"受害"情绪传递给他人。你不希望如此,因为这样会让别的员工泄气。

  为了对付消极谈话的潜在危险,识别四种有关的"带情绪的谈话"是有益的。如果你能认清这些消极方式,并把它转化成积极方式,就会鼓起你自己和同事的工作干劲。

变消极为积极

  这种消极谈话主要使我们下意识地受到限制和约束,要解决这个问题就要想法绕开约束或者干脆摆脱它们。

  当你碰到障碍时,是想办法绕过去,还是放弃?关键在于你对这个障碍是怎么想和怎么表述的,比如说:你要求员工将一份长篇报告复印许多份,明天一早送到相关人员手里。这时只剩半个小时取邮包的就要来了,偏偏复印机又坏了,办公大楼内其他复印机也不能正常工作,那该怎么办呢?

  你不想让员工和其他人消极地对待困难,应该说"把这个报告送出去有点困难,我想知道有什么方法可以克服这个困难?"

  为了确保员工能积极回应,你所说的每句话都应该朝积极的方向努力。当你听到有人说"干不了",你应该把他们向"能做到"的积极方向引导。比如,你可以建议扫描后把报告打印出来,或者通过E-mail把报告发给收件人。也就是说,积极地寻找替代方案的关键在于积极思考,而积极地思考往往能产生新点子,这样就不会鼓励员工放弃,而是让他们在现有条件下想办法。

变狭隘为开放

  狭隘指的是当你遇到困难时,认为只有一种或少数几种方法解决。比如说"Fred非常健忘,我想我不应该再把重要的工作交给他。"就是一种狭隘的说法,让你不想做点什么去改变Fred的健忘。狭隘的表述,使你先入为主,从而禁锢你的思想。

  为了避免消极对话,你经常需要把对话转向积极的、创新的讨论。这样有助于员工开放思想,不钻牛角尖。

  假如你听到一个经理在抱怨他的员工,不满意这个员工的工作表现。这位经理很沮丧,觉得这个员工自己不想努力,他说:"我不知道该怎么做,我可以炒他鱿鱼或者听之任之,但我真的不愿意这样做。"

  如果你让他只在前面两个方案中选择,这个经理就不能有效地解决这个问题。你可以说一些很简单的道理:"既然你不想采用以上两种办法,那么你可以想想别的办法。比如说让他每天给你交一份工作汇报,或者给他配一个导师,带着他一起把工作做好。"你的建议也许并不合适,但提醒了这个经理还有许多选择。
变责备为理解

  这种消极的谈话方式在企业里表现为"追究责任"。不管什么时候,你听到人们评价、责备自己或他人时,你应该立即把这种消极的对话转向积极的对话。你可以敦促人们更广泛地了解事情的来龙去脉来达到这个目的。

  比如说,当一条产品线落后于正常进度的时候,经理可能会说:"这是谁的责任?我想知道那些拖了我们后腿的生产车间工人的名字。"这就是一个"追究责任"的例子,这不可能改变目前的生产状况,也不能避免将来再次出现类似的情况。    经理人应该从另一个角度提问:"为什么会发生这样的事情?我们生产工序中的哪个部分出了问题才导致了产量下降?我们应该做些什么来改进工序以避免同样的问题再次发生?"这样的提问将鼓励员工去积极思索、提出建议而不是为自己开脱。

  当然,改变"追究责任"的方式带来的好处远不止在质量管理领域。当有人做了"错事"或"坏事",或犯了错误,如果你真的想从中吸取经验教训,你应该问为什么会发生这个事,而不是去追究责任。当你找到了哪个"为什么",而不是找到是"谁"干的,你就会了解事情的起因,做出调整,避免将来再犯错。

变对抗为合作

  对抗影响士气,让人们相互谴责,把精力耗费在扩大分歧上,而不是群策群力,共图大业。况且,感情上的伤害还会妨碍在工作中相互合作。

  你应该怎么处理这种对抗性的消极谈话呢?对策就是,鼓励人们问一问别人为什么要这么做,而不是告诉他应该怎么做。

  比如说,Ray向你抱怨Lyn很懒惰,借喝咖啡休息很长时间;而Lyn抱怨几乎不可能和Ray共事,因为他很粗鲁又不体谅人。你该做些什么让他们重归于好呢?

  首先,你需要弄清楚真相,最好让他们自己去发现。为什么Ray会在意Lyn喝咖啡时间的长短呢?为什么Lyn会觉得Ray粗鲁又不体谅人呢?如果你问了这些问题,就会发现:Ray的座位挨着Lyn,如果Lyn离开座位,Ray就要帮她接电话。Lyn回忆说几天前她离开了相当长一段时间回来后,Ray就说她偷懒,这让她很伤心,所以就不再和Ray说话。

  为了让他们重归于好,你应该运用理解力。只要理解了别人为什么那样做,你就不会做出愤怒的反应,而是建设性地沟通以化解矛盾。

  避免消极谈话,倡导积极谈话,比物质刺激更能起到激励作用。这是一项高回报的投资,无须成本就能带来巨大的回报:高涨的热情,干劲十足的员工和高效的业绩。

posted @ 2006-03-31 12:46 高山流水 阅读(166) | 评论 (0)编辑 收藏

 开始→运行→输入的命令集锦
mstsc--远程桌面连接
logoff--注销命令
rononce -p --15秒关机
tsshutdn--60秒倒计时关机命令
iexpress--木马捆绑工具,系统自带
tourstart--xp简介(安装完成后出现的漫游xp程序)
winchat--XP自带局域网聊天
sndrec32--录音机
Nslookup--IP地址侦测器
explorer--打开资源管理器
lusrmgr.msc--本机用户和组
services.msc---本地服务设置
oobe/msoobe /a--检查XP是否激活
notepad---打开记事本
cleanmgr--**整理
net start messenger--开始信使服务
compmgmt.msc---计算机管理
net stop messenger---停止信使服务
conf----启动 netmeeting
dvdplay---DVD播放器
charmap---启动字符映射表
diskmgmt.msc---磁盘管理实用程序
calc----启动计算器
dfrg.msc--磁盘碎片整理程序
chkdsk.exe---Chkdsk磁盘检查
devmgmt.msc--- 设备管理器
regsvr32 /u *.dll--停止dll文件运行
drwtsn32---- 系统医生
rononce -p --15秒关机
dxdiag----检查DirectX信息
regedt32--注册表编辑器
Msconfig.exe---系统配置实用程序
rsop.msc--组策略结果集
mem.exe---显示内存使用情况
regedit.exe--注册表
progman---程序管理器
winmsd----系统信息
perfmon.msc--计算机性能监测程序
winver----检查Windows版本
sfc /scannow---扫描错误并复原
taskmgr---任务管理器(2000/xp/2003)
wmimgmt.msc--打开windows管理体系结构(WMI)
wupdmgr---windows更新程序
w脚本---windows脚本宿主设置
write-----写字板
winmsd----系统信息
wiaacmgr--扫描仪和照相机向导
mem.exe---显示内存使用情况
Msconfig.exe---系统配置实用程序
mplayer2--简易widnows media player
mspaint---画图板
mplayer2--媒体播放机
magnify---放大镜实用程序
mmc-----打开控制台
mobsync---同步命令
dxdiag----检查DirectX信息
drwtsn32----系统医生
devmgmt.msc---设备管理器
dfrg.msc--磁盘碎片整理程序
diskmgmt.msc---磁盘管理实用程序
dcomcnfg--打开系统组件服务
ddeshare--打开DDE共享设置
dvdplay---DVD播放器
net stop messenger---停止信使服务
net start messenger--开始信使服务
notepad---打开记事本
nslookup--网络管理的工具向导
ntbackup--系统备份和还原
narrator--屏幕“讲述人”
ntmsmgr.msc--移动存储管理器
ntmsoprq.msc---移动存储管理员操作请求
netstat -an--(TC)命令检查接口
syncapp---创建一个公文包
sysedit---系统配置编辑器
sigverif--文件签名验证程序
sndrec32--录音机
shrpubw---创建共享文件夹
secpol.msc---本地安全策略
syskey----系统加密,一旦加密就不能解开,保护windows
xp系统的双重密码
services.msc---本地服务设置
Sndvol32--音量控制程序
sfc.exe---系统文件检查器
sfc /scannow---windows文件保护
taskmgr---任务管理器
eventvwr--事件查看器
eudcedit--造字程序
explorer--打开资源管理器
packager--对象包装程序
perfmon.msc--计算机性能监测程序
progman---程序管理器
regedit.exe--注册表
rsop.msc--组策略结果集
regedt32--注册表编辑器
regsvr32 /u *.dll--停止dll文件运行
regsvr32 /u zipfldr.dll----取消ZIP支持
cmd.exe---CMD命令提示符
chkdsk.exe---Chkdsk磁盘检查
certmgr.msc--证书管理实用程序
calc----启动计算器
charmap---启动字符映射表
cliconfg--SQL SERVER 客户端网络实用程序
Clipbrd---剪贴板查看器
conf----启动netmeeting
compmgmt.msc---计算机管理
cleanmgr--**整理
ciadv.msc----索引服务程序
osk-----打开屏幕键盘
odbcad32--ODBC数据源管理器
oobe/msoobe /a--检查XP是否激活
lusrmgr.msc--本机用户和组
Nslookup--IP地址侦测器
fsmgmt.msc---共享文件夹管理器
utilman---辅助工具管理器
gpedit.msc---组策略

posted @ 2006-03-31 12:44 高山流水 阅读(203) | 评论 (0)编辑 收藏

                                Java堆的管理--垃圾回收

作者:刘学超

作者简介

刘学超,华中师范大学计算机科学系网络与通讯研究所,你可以通过shuechao_lau@hotmail.com与他联系。

1  引言

Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。一般来说,堆的是由垃圾回收 来负责的,尽管JVM规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在实现的时候都有一个由垃圾回收所管理的堆。垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。

2  垃圾收集的意义

在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。

垃圾收集能自动释放内存空间,减轻编程的负担。这使Java 虚拟机具有一些优点。首先,它能使编程效率提高。在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。在用Java语言编程的时候,靠垃圾收集机制可大大缩短时间。其次是它保护程序的完整性, 垃圾收集是Java语言安全性策略的一个重要部份。

垃圾收集的一个潜在的缺点是它的开销影响程序性能。Java虚拟机必须追踪运行程序中有用的对象, 而且最终释放没用的对象。这一个过程需要花费处理器的时间。其次垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%收集到所有的废弃内存。当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。

3  垃圾收集的算法分析

Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。

大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就量正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。下面介绍几个常用的算法。

3.1  引用计数法(Reference Counting Collector)

引用计数法是唯一没有使用根集的垃圾回收得法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1。当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须 实时运行的程序。但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量 ,计数器加1,而每次现有对象出了作用域生,计数器减1。

3.2  tracing算法(Tracing Collector)

tracing算法是为了解决引用计数法的问题而提出,它使用了根集的概念。基于tracing算法的垃圾收集器从根集开始扫描,识别出哪些对象可达,哪些对象不可达,并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。在扫描识别过程中,基于tracing算法的垃圾收集也称为标记和清除(mark-and-sweep)垃圾收集器.

3.3  compacting算法(Compacting Collector)

为了解决堆碎片问题,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的过程中,算法将所有的对象移到堆的一端,堆的另一端就变成了一个相邻的空闲内存区,收集器会对它移动的所有对象的所有引用进行更新,使得这些引用 在新的位置能识别原来 的对象。在基于Compacting算法的收集器的实现中,一般增加句柄和句柄表。

3.4  coping算法(Coping Collector)

该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。它开始时把堆分成 一个对象 面和多个空闲面, 程序从对象面为对象分配空间,当对象满了,基于coping算法的垃圾 收集就从根集中扫描活动对象,并将每个 活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。

一种典型的基于coping算法的垃圾回收是stop-and-copy算法,它将堆分成对象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行。

3.5  generation算法(Generational Collector)

stop-and-copy垃圾收集器的一个缺陷是收集器必须复制所有的活动对象,这增加了程序等待时间,这是coping算法低效的原因。在程序设计中有这样的规律:多数对象存在的时间比较短,少数的存在时间比较长。因此,generation算法将堆分成两个或多个,每个子堆作为对象的一代(generation)。由于多数对象存在的时间比较短,随着程序丢弃不使用的对象,垃圾收集器将从最年轻的子堆中收集这些对象。在分代式的垃圾收集器运行后,上次运行存活下来的对象移到下一最高代的子堆中,由于老一代的子堆不会经常被回收,因而节省了时间。

3.6  adaptive算法(Adaptive Collector)

在特定的情况下,一些垃圾收集算法会优于其它算法。基于Adaptive算法的垃圾收集器就是监控当前堆的使用情况,并将选择适当算法的垃圾收集器。

4  透视Java垃圾回收

4.1  命令行参数透视垃圾收集器的运行

使用System.gc()可以不管JVM使用的是哪一种垃圾回收的算法,都可以请求Java的垃圾回收。在命令行中有一个参数-verbosegc可以查看Java使用的堆内存的情况,它的格式如下:

java -verbosegc classfile

可以看个例子:

class TestGC 
{
	public static void main(String[] args) 
	{
		new TestGC();
		System.gc();
		System.runFinalization();
	}
}

在这个例子中,一个新的对象被创建,由于它没有使用,所以该对象迅速地变为可达,程序编译后,执行命令: java -verbosegc TestGC 后结果为:

[Full GC 168K->97K(1984K), 0.0253873 secs]

机器的环境为,Windows 2000 + JDK1.3.1,箭头前后的数据168K和97K分别表示垃圾收集GC前后所有存活对象使用的内存容量,说明有168K-97K=71K的对象容量被回收,括号内的数据1984K为堆内存的总容量,收集所需要的时间是0.0253873秒(这个时间在每次执行的时候会有所不同)。

4.2  finalize方法透视垃圾收集器的运行

在JVM垃圾收集器收集一个对象之前 ,一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,Java提供了缺省机制来终止化该对象心释放资源,这个方法就是finalize()。它的原型为:

protected void finalize() throws Throwable

在finalize()方法返回之后,对象消失,垃圾收集开始执行。原型中的throws Throwable表示它可以抛出任何类型的异常。

之所以要使用finalize(),是由于有时需要采取与Java的普通方法不同的一种方法,通过分配内存来做一些具有C风格的事情。这主要可以通过"固有方法"来进行,它是从Java里调用非Java方法的一种方式。C和C++是目前唯一获得固有方法支持的语言。但由于它们能调用通过其他语言编写的子程序,所以能够有效地调用任何东西。在非Java代码内部,也许能调用C的malloc()系列函数,用它分配存储空间。而且除非调用了free(),否则存储空间不会得到释放,从而造成内存"漏洞"的出现。当然,free()是一个C和C++函数,所以我们需要在finalize()内部的一个固有方法中调用它。也就是说我们不能过多地使用finalize(),它并不是进行普通清除工作的理想场所。

在普通的清除工作中,为清除一个对象,那个对象的用户必须在希望进行清除的地点调用一个清除方法。这与C++"破坏器"的概念稍有抵触。在C++中,所有对象都会破坏(清除)。或者换句话说,所有对象都"应该"破坏。若将C++对象创建成一个本地对象,比如在堆栈中创建(在Java中是不可能的),那么清除或破坏工作就会在"结束花括号"所代表的、创建这个对象的作用域的末尾进行。若对象是用new创建的(类似于Java),那么当程序员调用C++的delete命令时(Java没有这个命令),就会调用相应的破坏器。若程序员忘记了,那么永远不会调用破坏器,我们最终得到的将是一个内存"漏洞",另外还包括对象的其他部分永远不会得到清除。

相反,Java不允许我们创建本地(局部)对象--无论如何都要使用new。但在Java中,没有"delete"命令来释放对象,因为垃圾收集器会帮助我们自动释放存储空间。所以如果站在比较简化的立场,我们可以说正是由于存在垃圾收集机制,所以Java没有破坏器。然而,随着以后学习的深入,就会知道垃圾收集器的存在并不能完全消除对破坏器的需要,或者说不能消除对破坏器代表的那种机制的需要(而且绝对不能直接调用finalize(),所以应尽量避免用它)。若希望执行除释放存储空间之外的其他某种形式的清除工作,仍然必须调用Java中的一个方法。它等价于C++的破坏器,只是没后者方便。

下面这个例子向大家展示了垃圾收集所经历的过程,并对前面的陈述进行了总结。

class Chair {
  static boolean gcrun = false;
  static boolean f = false;
  static int created = 0;
  static int finalized = 0;
  int i;
  Chair() {
    i = ++created;
    if(created == 47) 
      System.out.println("Created 47");
  }
  protected void finalize() {
    if(!gcrun) {
      gcrun = true;
      System.out.println(
        "Beginning to finalize after " +
        created + " Chairs have been created");
    }
    if(i == 47) {
      System.out.println(
        "Finalizing Chair #47, " +
        "Setting flag to stop Chair creation");
      f = true;
    }
    finalized++;
    if(finalized >= created)
      System.out.println(
        "All " + finalized + " finalized");
  }
}

public class Garbage {
  public static void main(String[] args) {
    if(args.length == 0) {
      System.err.println("Usage: \n" +
        "java Garbage before\n  or:\n" +
        "java Garbage after");
      return;
    }
    while(!Chair.f) {
      new Chair();
      new String("To take up space");
    }
    System.out.println(
      "After all Chairs have been created:\n" +
      "total created = " + Chair.created +
      ", total finalized = " + Chair.finalized);
    if(args[0].equals("before")) {
      System.out.println("gc():");
      System.gc();
      System.out.println("runFinalization():");
      System.runFinalization();
    }
    System.out.println("bye!");
    if(args[0].equals("after"))
      System.runFinalizersOnExit(true);
  }
}

上面这个程序创建了许多Chair对象,而且在垃圾收集器开始运行后的某些时候,程序会停止创建Chair。由于垃圾收集器可能在任何时间运行,所以我们不能准确知道它在何时启动。因此,程序用一个名为gcrun的标记来指出垃圾收集器是否已经开始运行。利用第二个标记f,Chair可告诉main()它应停止对象的生成。这两个标记都是在finalize()内部设置的,它调用于垃圾收集期间。另两个static变量--created以及finalized--分别用于跟踪已创建的对象数量以及垃圾收集器已进行完收尾工作的对象数量。最后,每个Chair都有它自己的(非static)int i,所以能跟踪了解它具体的编号是多少。编号为47的Chair进行完收尾工作后,标记会设为true,最终结束Chair对象的创建过程。(关于这个例子的更具体的分析和说明请参看《Java编程思想》的第四章)

5  关于垃圾收集的几点补充

经过上述的说明,可以发现垃圾回收有以下的几个特点:

(1)垃圾收集发生的不可预知性:由于实现了不同的垃圾收集算法和采用了不同的收集机制,所以它有可能是定时发生,有可能是当出现系统空闲CPU资源时发生,也有可能是和原始的垃圾收集一样,等到内存消耗出现极限时发生,这与垃圾收集器的选择和具体的设置都有关系。

(2)垃圾收集的精确性:主要包括2 个方面:(a)垃圾收集器能够精确标记活着的对象;(b)垃圾收集器能够精确地定位对象之间的引用关系。前者是完全地回收所有废弃对象的前提,否则就可能造成内存泄漏。而后者则是实现归并和复制等算法的必要条件。所有不可达对象都能够可靠地得到回收,所有对象都能够重新分配,允许对象的复制和对象内存的缩并,这样就有效地防止内存的支离破碎。

(3)现在有许多种不同的垃圾收集器,每种有其算法且其表现各异,既有当垃圾收集开始时就停止应用程序的运行,又有当垃圾收集开始时也允许应用程序的线程运行,还有在同一时间垃圾收集多线程运行。

(4)垃圾收集的实现和具体的JVM 以及JVM的内存模型有非常紧密的关系。不同的JVM 可能采用不同的垃圾收集,而JVM 的内存模型决定着该JVM可以采用哪些类型垃圾收集。现在,HotSpot 系列JVM中的内存系统都采用先进的面向对象的框架设计,这使得该系列JVM都可以采用最先进的垃圾收集。

(5)随着技术的发展,现代垃圾收集技术提供许多可选的垃圾收集器,而且在配置每种收集器的时候又可以设置不同的参数,这就使得根据不同的应用环境获得最优的应用性能成为可能。

针对以上特点,我们在使用的时候要注意:

(1)不要试图去假定垃圾收集发生的时间,这一切都是未知的。比如,方法中的一个临时对象在方法调用完毕后就变成了无用对象,这个时候它的内存就可以被释放。

(2)Java中提供了一些和垃圾收集打交道的类,而且提供了一种强行执行垃圾收集的方法--调用System.gc(),但这同样是个不确定的方法。Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。

(3)挑选适合自己的垃圾收集器。一般来说,如果系统没有特殊和苛刻的性能要求,可以采用JVM的缺省选项。否则可以考虑使用有针对性的垃圾收集器,比如增量收集器就比较适合实时性要求较高的系统之中。系统具有较高的配置,有比较多的闲置资源,可以考虑使用并行标记/清除收集器。

(4)关键的也是难把握的问题是内存泄漏。良好的编程习惯和严谨的编程态度永远是最重要的,不要让自己的一个小错误导致内存出现大漏洞。

(5)尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动设置为null,暗示垃圾收集器来收集该对象,还必须注意该引用的对象是否被监听,如果有,则要去掉监听器,然后再赋空值。

6  结束语

一般来说,Java开发人员可以不重视JVM中堆内存的分配和垃圾处理收集,但是,充分理解Java的这一特性可以让我们更有效地利用资源。同时要注意finalize()方法是Java的缺省机制,有时为确保对象资源的明确释放,可以编写自己的finalize方法。


posted 2005-01-21 09:24:00.0

posted @ 2006-03-31 12:44 高山流水 阅读(121) | 评论 (0)编辑 收藏

 

  查看数据库中有无多余的索引,即一个索引的字段为另一个索引的前几个字段。如index1的定义为test(filed1,filed2),index2的定义为test(filed1,filed2,filed3),则认为index1是多余的。(摘自Ixora)

						column redundant_index format a39
column sufficient_index format a39

select /*+ ordered */
  o1.name||'.'||n1.name  redundant_index,
  o2.name||'.'||n2.name  sufficient_index
from
  (
    select
      obj#,
      bo#,
      count(*)  cols,
      max(decode(pos#, 1, intcol#))  leadcol#
    from
      sys.icol$
    group by
      obj#,
      bo#
  )  ic1,
  sys.icol$  ic2,
  sys.ind$  i1,
  sys.obj$  n1,
  sys.obj$  n2,
  sys.user$  o1,
  sys.user$  o2
where
  ic2.obj# != ic1.obj# and
  ic2.bo# = ic1.bo# and
  ic2.pos# = 1 and
  ic2.intcol# = ic1.leadcol# and
  i1.obj# = ic1.obj# and
  bitand(i1.property, 1) = 0 and
  ic1.cols * (ic1.cols + 1) / 2 =
  ( select
      sum(xc1.pos#)
    from
      sys.icol$ xc1,
      sys.icol$ xc2
    where
      xc1.obj# = ic1.obj# and
      xc2.obj# = ic2.obj# and
      xc1.pos# = xc2.pos# and
      xc1.intcol# = xc2.intcol#
  ) and
  n1.obj# = ic1.obj# and
  n2.obj# = ic2.obj# and
  o1.user# = n1.owner# and
  o2.user# = n2.owner#
/
				

posted @ 2006-03-31 12:43 高山流水 阅读(121) | 评论 (0)编辑 收藏

 
<%@LANGUAGE="JAVASCRIPT"%>
<%
function hexdec(str)
{
    return parseInt(str,16);
}
										
function zeroFill(a,b)
{
    var z = hexdec(80000000);
    if (z & a)
    {
        a = a>>1;
        a &= ~z;
        a |= 0x40000000;
        a = a>>(b-1);
    }
    else
    {
        a = a >> b;
    }
    return (a);
}
function mix(a,b,c)
{
    a -= b; a -= c; a ^= (zeroFill(c,13));
    b -= c; b -= a; b ^= (a<<8);
    c -= a; c -= b; c ^= (zeroFill(b,13));
    a -= b; a -= c; a ^= (zeroFill(c,12));
    b -= c; b -= a; b ^= (a<<16);
    c -= a; c -= b; c ^= (zeroFill(b,5));
    a -= b; a -= c; a ^= (zeroFill(c,3));
    b -= c; b -= a; b ^= (a<<10);
    c -= a; c -= b; c ^= (zeroFill(b,15));
    var ret = new Array((a),(b),(c));
    return ret;
}
										
function GoogleCH(url,length)
{
    var init = 0xE6359A60;
    if (arguments.length == 1)
     length = url.length;  
    var a = 0x9E3779B9;
    var b = 0x9E3779B9;
    var c = 0xE6359A60;
    var k = 0;
    var len = length;
    var mixo = new Array();
    while(len >= 12)
    {
        a += (url[k+0] +(url[k+1]<<8) +(url[k+2]<<16) +(url[k+3]<<24));
        b += (url[k+4] +(url[k+5]<<8) +(url[k+6]<<16) +(url[k+7]<<24));
        c += (url[k+8] +(url[k+9]<<8) +(url[k+10]<<16)+(url[k+11]<<24));
        mixo = mix(a,b,c);
        a = mixo[0]; b = mixo[1]; c = mixo[2];
        k += 12;
        len -= 12;
    }
    c += length;
    switch(len)
    {
        case 11:
        c += url[k+10]<<24;
        case 10:
        c+=url[k+9]<<16;
        case 9 :
        c+=url[k+8]<<8;
        case 8 :
        b+=(url[k+7]<<24);
        case 7 :
        b+=(url[k+6]<<16);
        case 6 :
        b+=(url[k+5]<<8);
        case 5 :
        b+=(url[k+4]);
        case 4 :
        a+=(url[k+3]<<24);
        case 3 :
        a+=(url[k+2]<<16);
        case 2 :
        a+=(url[k+1]<<8);
        case 1 :
        a+=(url[k+0]);
    }
    mixo = mix(a,b,c);
    if (mixo[2] < 0)
    return (0x100000000 + mixo[2]);
    else
    return mixo[2];
}
										
function strord(s)
{
    var re = new Array();
    for(i=0;i<s.length;i++)
    {
        re[i] = s.charCodeAt(i);
    }
    return re;
}
function c32to8bit(arr32) 
{
    var arr8 = new Array(); 
    for(i=0;i<arr32.length;i++)
    {
     for (bitOrder=i*4;bitOrder<=i*4+3;bitOrder++)
     {
            arr8[bitOrder]=arr32[i]&255;
            arr32[i]=zeroFill(arr32[i], 8);
        }
    }
    return arr8;
}
function myfmod(x,y)
{
 var i = Math.floor(x/y);
        return (x - i*y);
}
										
function GoogleNewCh(ch)
{
 ch = (((ch/7) << 2) | ((myfmod(ch,13))&7));
 prbuf = new Array();
 prbuf[0] = ch;
 for(i = 1; i < 20; i++) {
       prbuf[i] = prbuf[i-1]-9;
 }
 ch = GoogleCH(c32to8bit(prbuf), 80);
 return ch;
  
}
function URLencode(sStr)
{
return encodeURIComponent(sStr).replace(/\+/g,"%2B").replace(/\//g,"%2F");
}
function getGoogleHostInfo(url){
    var reqgr = "info:" + url;
    var reqgre = "info:" + URLencode(url);
 //Response.Write(reqgr+"<br>"+reqgre);
    gch = GoogleCH(strord(reqgr));
    gch = "6" + GoogleNewCh(gch);
    var querystring = "http://toolbarqueries.google.com/search?client=navclient-auto&ch=" + gch + "&ie=UTF-8&oe=UTF-8&features=Rank:FVN&q=" + reqgre;
 //Response.Write(querystring);
 var objXMLHTTP, xml;
 xml = Server.CreateObject("Microsoft.XMLHTTP");
 xml.Open("GET", querystring, false);
 xml.setRequestHeader( "User-Agent", "Mozilla/4.0 (compatible; GoogleToolbar 2.0.114-big; Windows XP 5.1)" );
 xml.send();
 //Response.Write(xml.responseText);
 //Response.Write(xml.responseBody);
 return xml.responseText;
}
function getPageRank(temp){
  var foo = temp.match(/Rank_.*?:.*?:(\d+)/i);
  var pr = (foo) ? foo[1] : "";
  return pr;
}
function getDirectory(temp){
  var  foo = temp.match(/FVN_.*?:.*?:(?:Top\/)?([^\s]+)/i);
  var cat = (foo) ? foo[1] : "";
  if(cat!="")cat="http://directory.google.com/Top/"+cat
  return cat;
}
var site;
site=Request.Form("site");
if(site!="undefined"){
 var google=getGoogleHostInfo(site);
 var pagerank=getPageRank(google);
 var directory=getDirectory(google);
 Response.Write("PageRank:"+pagerank+"<br>");
 Response.Write("PageRank:<img src=\"images/pr"+pagerank+".png\" alt=\"PageRank:"+pagerank+"\"><br>");
 Response.Write("网站:"+site+"<br>");
 if(directory!="")Response.Write("所在目录:<a href="+directory+">"+directory+"</a><br>");
}
%>
<%
										
%>
<form method=post>
<input name="site" type="text" size="50">
<input type="submit" value="Query">
</form>
demo:http://www.asroad.net/test/www.asp

posted @ 2006-03-31 12:42 高山流水 阅读(75) | 评论 (0)编辑 收藏

     摘要: 自从 oracke 7.3 以来, oracle 提供了一种新的 join 技术,就是 hash join 。 Hash Join 只能用于相等连接,且只能在 CBO 优化器模式下。相对于 nested loop join , hash join ...  阅读全文

posted @ 2006-03-31 12:03 高山流水 阅读(4073) | 评论 (0)编辑 收藏

全球采购网站www.123trading.com 是全球领先的电子商务交易平台, 致力于整合互联网技术与传统工业资源,协助全球采购商和供应商高效而安全地进行网上供应和采购,同时为全球制造商、进口商、出口商、零售商、批发商提供快速而简捷的国际贸易和电子商务解决方案, 以低成本、高效益帮助全球企业快速实现进出口和国内贸易。目前委托全球采购网站www.123trading.com 进行采购的著名国际买家包括《财富》“世界500强”中的219家企业, 《剑桥制造评论》“中国1000大制造商”中的568家企业。全球采购网站www.123trading.com 总结出跟老外沟通绝招--成功做外贸34招。
  
第1招 妥善安排会面的约定

  —I'd like to make an appointment with Mr. Lee.
  当你计划到海外出差,顺道拜访客户时,必须先以书信通知对方。出国以前再以Telex或电话向对方确认访问的日期和目的。如果是临时决定的拜访,也要通过对方的秘书安排,告诉 她:"I'd like to make an appointment with Mr.Lee."(我想和李先生约见一次。)让对方对你的造访有所准备,才会有心情和你洽谈。

第2招 向沟通对手表示善意与欢迎

  --I will arrange everything.

  如果沟通是由你发起,提供对手一切的方便,能使沟通一开始便在友善和谐的气氛下进行。尤其是当你的沟通对手是远道而来的,你热心地告知他:“I will arrange everything." (我会安排一切。)不但表现出你的诚意,也能使他在不必顾虑食宿等琐事的情况下,专心与你进行沟通。

第3招 沟通进行中应避免干扰

  —No interruptions during the meeting!

  如果沟通的地点是在你的公司,那么请叮咛你的部属,勿在沟通过程中做不必要的干扰。因为过份的干扰会影响沟通的意愿和热忱。

第4招 遵守礼仪

  --Behave yourself!

  沟通时,仍然要遵守一般奉行的礼仪和保持良好的仪态,这样可以增加人们对你的好感,提高你的沟通效率。此外,坐姿不良,在对手讲话时左顾右盼,都足以使人对体产生不良的印象,而减低与你洽谈的兴致。

第5招 适时承认自己的过失

  --It's my fault.

  如果你明显地犯了错,并且对别人造成或大或小的伤害,一句充满歉意的“I'm sorry. It's my fault."(对不起,是我的错。)通常能够获得对方的原谅。就算他实在很懊恼,至少也能稍微缓和一下情绪。做无谓的辩解,只能火上加油,扩大事端。

第6招 抱怨不是无理取闹

  —I have a complaint to make.

  以激愤的语气向人抱怨某事,很可能令人心生反感,而使结果适得其反。服务员上错了菜,旅馆女服务员忘了整理你的房间,送来的货物根本不是你订单上所指明的东西等情况,着实令人懊恼。但是生气并不能解决问题,不如心平气和而语气坚定地告诉对方 "I have a complaint to make.”(我有怨言。)然后告诉他所发生的事。

第7招 资料须充实完备

  —We have a pamphlet in English.
  具体的物品通常比口头描述更有说服力。当客户听到你说 "We have a pamphlet in English."(我们有英文的小册子。)或 "Please take this as a sample"(请将这个拿去当样品。)时,一定会兴趣大增,进而问你许多和产品有关的问题。如果你平时资料搜集得全面,便能有问必答。这在商务沟通上是非常有利的。
第8招 缓和紧张的气氛

  --How abouta break?

  当会议因冗长而陷于沉闷、紧张的气氛时,做无意义的僵持是无法获得令人满意的结果的。如果能在不打断对方的情形下提出“How about a break?”(休息一下如何?)对方必能欣然接受,紧张的气氛也立刻得以经解。当你们再回到会议桌时,也能以清晰的思路继续沟通。

第9招 做个周到的主人
  —You can use our office equipment if necessary.

  如果沟通是在你的公司进行,除了应向沟通对手提供舒适的场所以外,更应该尽量配合对手,向他提供有助于沟通进行的服务与设备。例如,大大方方地告诉他“ You can use our office equipment if necessary.”(如果必要的话,您可以使用我们的办公室设备。)协助对手对沟通内容做正确的衡量,其结果可能也是对己方极为有利的。

第10招 询问对方的意见
  —What is your opinion?

  每个人都希望自己的意见受到重视。当你和他人进行沟通时,除了说出自己的想法以外,随时可加上一句“What is your opinion?”(你的意见是?)或“ I'd like to hear your ideas about the problem.”(我想听听你对这个问题的看法。)不但让对方感觉受到重视,更能使你们因思想的交流而逐渐达成协议。

第11招 清楚地说出自己的想法与决定
  —I think I should call a lawyer.

  如果在沟通场合中,你无法详实地说出心中的意念,不仅会使对方听得满头雾水,说不定还会让对方认为你对实际情形根本不了解,而失去和你沟通的兴致。试想假如你在向警察描述车祸的发生时,不能提醒他“Ihad theright-of-way."(我有优先行驶权。)或没告诉他“ I think I should call a lawyer."(我想我该叫个律师。)你也许因此而吃了大亏。还有很多情况是特别需要提供详实资料的,例如:向医生叙述你的病痛,告诉理发师你所要的发型,向客户讲解产品的特性等。平常多注意英美人士对这类场合的应对,您这方面的英语一定会大有进步!

第12招 找出问题症结
  --What seems to be the trouble?

  任何一个冲突或误解的产生,都有潜在原因。为什么你的老客户这回不向你的公司订货?为什么对方不能达到你的要求?这种情况发生时,要立刻积极地探索原因。向对方探询“What seems to be the troubte?”(有什么困难吗?)或问一句“Is there something that needs our attention?" 有什么需要我们注意的吗?)都能表示你对事情的关切。知道问题的症结,才有办法进行沟通。

第13招 要有解决问题的诚意
  —Please tell me about it.

  当客户向你提出抱怨时,你应该做的事是设法安抚他。最好的办法就是对他提出的抱怨表示关切与解决的诚意。你的一句“Please tell me about it”(请告诉我这件事的情况。)或“I'm sorry for my error and assure you I will take great care in performing the work”(我为我的错误感到抱歉,并向您保证,我会尽全力处理此事。)令对方觉得你有责任感,也会恢复对你的信任。

第14招 适时提出建议
  --We'll send you a replacement right away.
  当损失已经造成时,适时地提出补救方法,往往能使沟通免于陷入僵局,甚至于得以圆满地达成协议。例如:你运送到客户手上的货物,的确不是订单上所标明的,而你又能立即向他保证 "We'll send you a replacement right away." (我们会立即寄给您一批替换品。)或者告诉他“We can adjust the price for you if you keep the material.”(如果您留下这批材料,我们可以为您调整价格。)那么,客户心中的忧虑必定立刻减半,而愿意考虑您的提议。

第15招 随时确认重要的细节
  —Is this waht we decided?

  商务洽谈中,一牵扯到金额、交货条件和日期时,除了洽谈当时要用口头复述加以确认外,合约拟好后,更要详细地过目一遍。一旦发现疑点,应立刻询问对方“Is this what we decided? ”(这是我们说定的吗?)合约内容真的错得离谱,就应告诉对方“I'll have to return this contract to you unsigned."(我得将这份合约退还给你,不能签名。)以示抗议。任何合约上的问题,宁可罗嗦一点,也决不可含糊。

第16招 听不懂对方所说的话时,务必请他重复
  —Would you mind repeating it?

  英语不是我们的母语,听不懂是很自然的。听不懂又装懂,那才是有害的。其实请人家重复或再讲清楚一点并不难,你只要说”Would you mind repeating it?"(您介意再讲一遍吗?),相信对方不但会再说一遍,而且连速度都会放慢些。如果你还是没听懂,那么仍然要用这个老方法:“Could you explain it more precisely?”(您能解释得更明白一点吗?)

第17招 使谈判对手作肯定答复的问题
  —Is it important that …?

  连续发问沟通对手给予肯定答复的问题,最后引导他对你的主要建议也作有定的答复,是绝对须要花费一番心思的。通常沟通对手只对自己有利的问题,才会痛快地回答“Yes”。因此,在沟通场合开始前,不妨先细心地想一下,你所希望对方接受的条件,对他有什么好处,试着以“Is it important that …?”(…是不是对您很重要?)或“Is it helpful if …?”(如果…是不是对你有帮助?)未获得他的肯定,那么要使你的建议通过也不难了。

第18招 做适当的让步
  —The best compromise we can maks is...

  沟通双方的互相让步,最常见的例子就是讨价还价。买方希望卖方减价一百五十元,而卖方只想减价五十元,双方一阵讨价还价之后,最后减了一百元。不论你的对手是如何的咄咄逼人,你总得做一个最后的让步:“The best compromise we can make is … ”(我们所能做的最好的折衷办法是…)或是“ This is the lowest possible price.”(这是最低的可能价格了。)然后坚定不移,否则如果让步得太过,你可就要有所损失了。

第19招 不要仓促地做决定
  —Please let me think it over.

  在商场上讲求信用,一旦允诺人家的事情,要再反悔,会令人产生不良印象。因此,在下决定之前,务必要经过深思熟虑。如果你正在和客户商谈一件无法遂下决定的事时,不妨请他给你一点时间“Please let me think it over.”(请让我考虑一下。)或“ Would it be all right to give you an answer tomorrow?”(明天再答复您行吗?)切记,仓促地下决定往往招致严重的后果!

第20招 说“不”的技巧
  --No, but …

  在商务沟通上,该拒绝时,就应该斩钉截铁地说“No.”拐弯抹角地用“That's difficult"(那很困难。)或“Yes, but..."(好是好,可是…)来搪塞,会令对方觉得你答应得不够干脆,而不是在委婉地拒绝。如果你说“No,but…”对方便清楚地知道你是拒绝了,但似乎还可以谈谈。这个时候,你因为已先用“No”牵制对方,而站在沟通的有利位置上了。

第21招 不要催促对手下决定
  --Stop asking "Have you decided?"

  当你的沟通对方需要时间来考虑一下方案时,千万不要一直催促他“Hare you decided?”(你决定了没有?)那样,你不但干扰了他的思考,也可能激怒他。结果原本可能达成的协议或许就此泡汤了。

第22招 沉默是金
  —Silence is golden.

  面对对方所提无法接受的提议,沉默是最有力的回答。这种无动于衷所带给沟通对手的压力,远大于浇他一盆冷水。将所达成的协议逐一列入记录—— Let's have the agreed items recorded.为了避免签约时的争执或重新商议,交涉中达成协议的项目应做成记录,并在会议结束时传阅。因此,每达成一项协议,要记得提醒对方“Let's have the agreed items recorded." 我们声达成协议的项目记录下来。)

第23招 过分吹牛,足以败事
  --Don't boast!

  磋商者往往为了达成协议而向交涉对手做过份不实的吹嘘。这种情形在向他人推销产品时,尤其常见。顾客因听信你的吹牛而购买产品,进而造成损失,轻者不再与你打交道;严重的,恐怕还要告你欺诈,多划不来!所以在向他人做“ We can give you a guarantee 100 years.”(我们可以给您一百年的保证。)这一类的承诺时,最好先斟酌一番。

第24招 不浪费沟通对手的时间
  -- ...then I'll drive you to the airport for your flight at 7:00.

  在沟通开始以前,最好事先得知沟通对手的行程表,并尽量配合。当你和客户谈好了一切细节以后,你对他说“I'll have my secretary type the contract for you to sign at once, then I'll drive you to the airport for your flight at 7:00. (我会让我的秘书立刻将合同打好给您签名,然后,我开车送您去机场搭七点钟的飞机。)想必他一定会感激你的周到细心,因此也会采取合作的态度。

第25招 电子采购: 集约经营的法宝!
  —internet is King.

  面对日趋频繁的跨国公司全球采购,国内许多企业缺乏与全球采购系统对接的经验,不知该如何将产品通过全球采购平台打入国际市场。目前全球采购网站http://www.123trading.com可以充当这个桥梁! 在给对方钱之前, 最好到123trading.com查询一下对方的信用记录! 全球采购网站www.123trading.com 以其庞大的海外采购商网络与世界领先的国际贸易交易平台, 吸引众多国际知名买家加盟直接自中国采购,并广泛征集、筛选和培养合格的中国供应商,极大地促进中国企业和海外买家直接对话,更深更广地参与国际贸易,实现出口创汇。

第26招 达到目地,立即离开
  —I'm glad to have met you, Mr. Lee.

  如果协议达成,而你仍流连忘返,则有以下两种危险:沟通对手改变主意;或者你可能因松懈而目不择言,说错了话。因此商议一完成,立即以 "I'm glad to have met you, Mr. Lee."(李先生,很高兴认识您。)收场,告别离去。
第27招 充满信心地进行沟通
  —You can ask me any question.

  任何有心沟通的人,都希望他的沟通对手是个举足轻重的人物。让对手认为你是有决策力的人,最直接的方法便是一见面就告诉他“ You can ask me anyquestion.”(您可以问我任何问题。)如果你在对方面前处处显得紧张兮兮,不是一直抽烟,就是不断干咳,对方必定会怀疑他跟你之间的沟通效果。因此面对每一个沟通场合,一定要充满信心。

第28招 对沟通对手的专长与能力表示认知
  --I know you are good at ….

  每个人都对自己的才能引以为荣。向你的沟通对手表示你认知他的能力,并寄希望他有所表现:“I know you are good at handling difficult situations, and I believe I can count on you."(我知道你擅于处理棘手问题,并相信我可以依赖您。)相信他一定不愿意让你失望。

第29招 以肯定的语气,谈论对手的问题
  —I believe our experts can give you helpful advice for the problem in your company.
  当对手正在为某个问题烦恼,而你正好能够帮他忙,一句 "I believe our experts can give you helpful advice for the problem in your company." (我相信我们的专家能提供对贵公司问题有帮助的建议。)必能使他宽慰不已,立刻表现合作的态度,而你的
沟通力也大大增加了。

第30招 委婉地透露坏消息
  —Bad news,I'm afraid.

  要向他人透露坏消息,也需要一点技巧。老师在公布成绩以前,总是光透露有多少人不及格,以使考得不好的同学预先做好心理准备。同样,在向客户透露涨价或其它坏消息时,先告诉他“Bad news,I'm afraid”(恐怕是坏消息喔。)也能收到相同的效果。人对某件事的发生预先有心理准备时,总是较容易接受
的。

第31招 强调沟通双方相同的处境
  —Our costs are way up too.

  说服沟通对手的技巧之一,就是强调双方的相同点,使其产生认同感,进而达成协议。一个卖主告诉老客户产品涨价的最常见理由就是“ Our costs are way up too, " (我们的成本也上涨了。)以使客户觉得他的对手和他一样,正面临着涨价的处境。这时候买主再不愿意,也只好接受涨价的必然结果了。

第32招 向谈判对手略施压力
  —The special price will be effective until May 30.

  为了促使谈判对手尽快做决定,略施压力有时也是值得考虑的手段。例如,聪明的卖主都知道,订出“最后期限”,能够刺激原本无心购买或犹豫不决的买主。一句“ Unless you ordr in February, we won't be able to deliver in April.”(除非您在二月就下订单,否则我们无法在四月交货。)或者“ The Special price will be effective until Mag 30.”(特价的有效期限到五月三十日。)都能使潜在的买主迅速地在心里盘算一番!

第33招 不要幸灾乐祸
  --Don't say“ I told you so!"

  当你以前曾告诉或警告过对手的事被你不幸言中时,用不着再来提醒他“I told you so!" 我告诉过你吧!)这种话对你们的沟通没有帮助,却只有使听者更加反感。

第34招 保留沟通对手的面子
  —Your views regarding management differ from mine.

要使沟通彻底失败,最好的办法就是使你的沟通对手颜面尽失。可是,这该不是你所要的结果吧?因为如此一来,沟通不但要破裂,也会招来对手的怨恨。虽然你重重地打击了对手,自己却也成了失败的沟通者。因此向对方提出质疑时,要确定将矛头指向事情本身,而不是对手身上:“Your views regarding management differ mine.”(您的经营观点和我的不同。)有时候,你甚至于可以将责任归咎于不在场的第三者身上,而不是直接推给沟通对手:" Someone must have given you wrong information."(一定是有人把错误的情报给了你。)这样的说法可以引导对方修正他的观点,而不会触怒了他,使他拂袖而去。 

两年多的艰苦实践,奠定了全球采购网站www.123trading.com 的行业基础和实战经验。两年来,深入全国各大城市,有规模地组织了1000多场电子商务、信用管理、社会责任和出口战略培训,此外,巡回举办高质量的"全球采购招商会",采购项目涉及电器、服装、化工、食品等30多个行业,数十万种产品。

posted @ 2006-03-31 12:03 高山流水 阅读(137) | 评论 (0)编辑 收藏

 

SDK提供了有序集合接口java.util.List的几种实现,其中三种最为人们熟知的是Vector、ArrayList和LinkedList。有关这些List类的性能差别是一个经常被问及的问题。在这篇文章中,我要探讨的就是LinkedList和Vector/ArrayList之间的性能差异。

为全面分析这些类之间的性能差异,我们必须知道它们的实现方法。因此,接下来我首先从性能的角度出发,简要介绍这些类的实现特点。

一、Vector和ArrayList的实现

Vector和ArrayList都带有一个底层的Object[]数组,这个Object[]数组用来保存元素。通过索引访问元素时,只需简单地通过索引访问内部数组的元素:

public Object get(int index)
{ // 首先检查index是否合法...此处不显示这部分代码 return
elementData[index]; }

内部数组可以大于Vector/ArrayList对象拥有元素的数量,两者的差值作为剩余空间,以便实现快速添加新元素。有了剩余空间,添加元素变得非常简单,只需把新的元素保存到内部数组中的一个空余的位置,然后为新的空余位置增加索引值:

public boolean add(Object o)
{ ensureCapacity(size + 1); // 稍后介绍 elementData[size++] = o; return true;
// List.add(Object) 的返回值 }

把元素插入集合中任意指定的位置(而不是集合的末尾)略微复杂一点:插入点之上的所有数组元素都必须向前移动一个位置,然后才能进行赋值:

public void add(int index, Object element) {
// 首先检查index是否合法...此处不显示这部分代码
ensureCapacity(size+1);
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}

剩余空间被用光时,如果需要加入更多的元素,Vector/ArrayList对象必须用一个更大的新数组替换其内部Object[]数组,把所有的数组元素复制到新的数组。根据SDK版本的不同,新的数组要比原来的大50%或者100%(下面显示的代码把数组扩大100%):

public void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = Math.max(oldCapacity * 2, minCapacity);
elementData = new Object[newCapacity];
System.arraycopy(oldData, 0, elementData, 0, size);
}
}

Vector类和ArrayList类的主要不同之处在于同步。除了两个只用于串行化的方法,没有一个ArrayList的方法具有同步执行的能力;相反,Vector的大多数方法具有同步能力,或直接或间接。因此,Vector是线程安全的,但ArrayList不是。这使得ArrayList要比Vector快速。对于一些最新的JVM,两个类在速度上的差异可以忽略不计:严格地说,对于这些JVM,这两个类在速度上的差异小于比较这些类性能的测试所显示的时间差异。

通过索引访问和更新元素时,Vector和ArrayList的实现有着卓越的性能,因为不存在除范围检查之外的其他开销。除非内部数组空间耗尽必须进行扩展,否则,向列表的末尾添加元素或者从列表的末尾删除元素时,都同样有着优秀的性能。插入元素和删除元素总是要进行数组复制(当数组先必须进行扩展时,需要两次复制)。被复制元素的数量和[size-index]成比例,即和插入/删除点到集合中最后索引位置之间的距离成比例。对于插入操作,把元素插入到集合最前面(索引0)时性能最差,插入到集合最后面时(最后一个现有元素之后)时性能最好。随着集合规模的增大,数组复制的开销也迅速增加,因为每次插入操作必须复制的元素数量增加了。

二、LinkedList的实现

LinkedList通过一个双向链接的节点列表实现。要通过索引访问元素,你必须查找所有节点,直至找到目标节点:

public Object get(intindex) {
// 首先检查index是否合法...此处不显示这部分代码
Entry e = header; // 开始节点
// 向前或者向后查找,具体由哪一个方向距离较
// 近决定
if (index < size/2) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}

把元素插入列表很简单:找到指定索引的节点,然后紧靠该节点之前插入一个新节点:

public void add(int index, Object element) {
// 首先检查index是否合法...此处不显示这部分代码
Entry e = header; // starting node
// 向前或者向后查找,具体由哪一个方向距离较
// 近决定
if (index < size/2) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
Entry newEntry = new Entry(element, e, e.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
}

线程安全的LinkedList和其他集合
如果要从Java SDK得到一个线程安全的LinkedList,你可以利用一个同步封装器从Collections.synchronizedList(List)得到一个。然而,使用同步封装器相当于加入了一个间接层,它会带来昂贵的性能代价。当封装器把调用传递给被封装的方法时,每一个方法都需要增加一次额外的方法调用,经过同步封装器封装的方法会比未经封装的方法慢二到三倍。对于象搜索之类的复杂操作,这种间接调用所带来的开销不是很突出;但对于比较简单的方法,比如访问功能或者更新功能,这种开销可能对性能造成严重的影响。

这意味着,和Vector相比,经过同步封装的LinkedList在性能上处于显著的劣势,因为Vector不需要为了线程安全而进行任何额外的间接调用。如果你想要有一个线程安全的LinkedList,你可以复制LinkedList类并让几个必要的方法同步,这样你可以得到一个速度更快的实现。对于所有其它集合类,这一点都同样有效:只有List和Map具有高效的线程安全实现(分别是Vector和Hashtable类)。有趣的是,这两个高效的线程安全类的存在只是为了向后兼容,而不是出于性能上的考虑。

对于通过索引访问和更新元素,LinkedList实现的性能开销略大一点,因为访问任意一个索引都要求跨越多个节点。插入元素时除了有跨越多个节点的性能开销之外,还要有另外一个开销,即创建节点对象的开销。在优势方面,LinkedList实现的插入和删除操作没有其他开销,因此,插入-删除开销几乎完全依赖于插入-删除点离集合末尾的远近。

三、性能测试

这些类有许多不同的功能可以进行测试。LinkedList应用比较频繁,因为人们认为它在随机插入和删除操作时具有较好的性能。所以,下面我分析的重点将是插入操作的性能,即,构造集合。我测试并比较了LinkedList和ArrayList,因为这两者都是非同步的。

插入操作的速度主要由集合的大小和元素插入的位置决定。当插入点的位置在集合的两端和中间时,最差的插入性能和最好的插入性能都有机会出现。因此,我选择了三个插入位置(集合的开头、末尾和中间),三种典型的集合大小:中等(100个元素),大型(10,000个元素),超大型(1,000,000个元素)。

在本文的测试中,我使用的是JAVA SDK 1.2.0和1.3.0系列的SUN JVM。此外,我还用HOTSPOT JVM 2.0进行了测试,这个版本可以在1.3.0 SDK找到。在下面的表格中,各个测量得到的时间都以其中一次SDK 1.2 VM上的测试时间(表格中显示为100%的单元)为基准显示。测试期间使用了默认的JVM配置,即启用了JIT编译,因此对于所有JVM,堆空间都必须进行扩展,以避免内存溢出错误。表格中记录的时间是多次测试的平均时间。为了避免垃圾收集的影响,在各次测试之间我强制进行了完全的内存清理(参见测试源代码了解详情)。磁盘监测确保磁盘分页不会在测试过程中出现(任何测试,如果它显示出严重的磁盘分页操作,则被丢弃)。所有显示出数秒应答时间的速度太慢的测试都重复进行,直至记录到一个明显合理的时间。

表1:构造一个中等大小的集合(100个元素)。括号中的数字针对预先确定大小的集合。

 

1.2 JVM

1.3 JVM

HotSpot 2.0 JVM

总是插入到ArrayList的开头

100% (48.0%)

184.9% (152.0%)

108.0% (66.7%)

总是插入到LinkedList的开头

135.5%

109.1%

85.3%

总是插入到ArrayList的中间

130.0% (40.6%)

187.4% (158.0%)

84.7% (46.0%)

总是插入到LinkedList的中间

174.0%

135.0%

102.3%

总是插入到ArrayList的末尾

63.3% (20.7%)

65.9% (25.0%)

60.3% (29.3%)

总是插入到LinkedList的末尾

106.7%

86.3%

80.3%

对于规模较小的集合,ArrayList和LinkedList的性能很接近。当元素插入到集合的末尾时,即追加元素时,ArrayList的性能出现了突变。然而,追加元素是ArrayList特别为其优化的一个操作:如果你只想要一个固定大小的静态集合,Java数组(例如Object[])比任何集合对象都具有更好的性能。除了追加操作,测量得到的时间数据差别不是很大,它们反映了各个JVM的优化程度,而不是其他什么东西。

例如,对于把元素插入到集合的开始位置来说(表1的前两行),HotSpot 2.0 JVM加LinkedList具有最好的性能(85.3%),处于第二位的是 1.2 JVM加ArrayList(100%)。这两个结果显示出,1.2中简单的JIT编译器在执行迭代和复制数组等简单的操作时具有很高的效率。在HotSpot中复杂的JVM加上优化的编译器能够改进复杂操作的性能,比如对象创建(创建LinkedList节点),并能够利用代码内嵌(code-inlining)的优势。1.3 JVM的结果似乎显示出,在简单操作方面它的性能有着很大的不足,这一点很可能在以后的JVM版本中得到改进。

在这里我特别进行测试的是ArrayList相对于LinkedList的另一个优点,即预先确定集合大小的能力。具体地说,创建ArrayList的时候允许指定一个具体的大小(例如,在测试中ArrayList可以创建为拥有100个元素的容量),从而避免所有随着元素增多而增加集合规模的开销。表1括号中的数字显示了预先确定集合大小时性能的提高程度。LinkedList(直到 SDK 1.3)不能预先确定大小。

此外,ArrayList只生成少量的需要进行垃圾收集的对象,即,用来保存元素的内部数组对象,以及每次ArrayList容量不足需要进行扩展时创建的附加内部数组对象。LinkedList不管可能出现的任何删除操作,都为每一个插入操作生成一个节点对象。因此,LinkedList会给垃圾收集器带来相当多的工作。考虑到这些因素,对于任何中小规模的集合,我会选择使用ArrayList而不是LinkedList。

表2:构造一个大型集合(10,000个元素)

 

1.2 JVM

1.3 JVM

HotSpot 2.0 JVM

总是插入到ArrayList的开头

7773%

7537%

7500%

总是插入到LinkedList的开头

100%

90.34%

65.6%

总是插入到ArrayList的中间

3318%

3412%

3121%

总是插入到LinkedList的中间

26264%

14315%

14209%

总是插入到ArrayList的末尾

41.4%

41.2%

37.5%

总是插入到LinkedList的末尾

66.4%

73.9%

61.7%

表2显示了大规模集合的测试结果。可以看到,在出现大规模插入操作的时候,我们开始遭遇严厉的性能惩罚。正如我们前面分析类的实现所得到的结果,对于LinkedList来说最差的情形出现在把元素插入到集合中间时。另外我们还可以看到,与使用ArrayList时把元素插入到集合开头的最差性能相比,使用LinkedList时把元素插入到集合中间的性能更差一些。和这两种性能最差的情况相比,把元素插入到ArrayList中间的性能显然要好得多。

总地看来,ArrayList再一次在大多数情形下表现出更好的性能,包括根据索引把元素插入到随机位置的情形。如果你总是要把元素插入到集合中靠前的位置,LinkedList具有更好的性能;然而,此时你可以利用一个反向的ArrayList得到更好的性能,即,使用一个专用的实现,或者通过[size -index]映射翻转索引在集合中的位置。

表3:构造一个超大集合(1,000,000个元素)

 

1.2 JVM

1.3 JVM

HotSpot 2.0 JVM

总是插入到ArrayList的开头

太长

太长

太长

总是插入到LinkedList的开头

100%

179.5%

144.1%

总是插入到ArrayList的中间

太长

太长

太长

总是插入到LinkedList的中间

太长

太长

太长

总是插入到ArrayList的末尾

38.3%

47.7%

42.9%

总是插入到LinkedList的末尾

65.1%

161.5%

139.9%

表3显示了超大集合的测试结果,从该表可以得出的结论与表2非常相似。然而,表3强调的是,超大集合要求数据、集合类型、数据处理算法之间的恰到好处的配合;否则,你将得到事实上不可接受的性能表现。至于性能优化,你可以构造一个针对该问题的专用集合类。对于超大集合来说,为了获得可接受的性能,构造专用集合类往往是很有必要的。

四、查询的性能

在类的内部实现查询时查询的性能最高。对于查询这些列表来说,迭代所有元素所需要的时间是一个限制因素。ArrayList/Vector类中实现的查询将对类的元素进行迭代。下面的例子计算空元素的总数量:

int count = 0;
for (int i = 0; i < size; i++)
if(elementData[i] == null)
count++;

LinkedList类中实现的查询将搜索所有的节点。下面的例子计算所有空元素的总数量:
node = header.next;
count = 0;
for (int i = 0; i < repeat; i++, node = node.next)
if (node.element == null)
count++;

表4显示出,ArrayList的性能显著地超过了LinkedList,它再一次显示出ArrayList应该是我们首选的类。表5显示了利用从List.listIterator(int)获得的ListIterator对象迭代所有元素所需要的时间,如果查询机制不能在List内部实现,这些迭代器是必需的。ArrayList再一次显示出了较高的性能,但这次性能的差异程度不象表4显示的那样不可思议。注意,表5所显示的绝对时间相当于表4显示绝对时间的10倍,即,ArrayList内部遍历大约比ArrayList利用ListIterator迭代要快10倍。

表4:通过内部访问迭代集合中的所有元素

 

1.2 JVM

1.3 JVM

HotSpot 2.0 JVM

ArrayList内部搜索

100%

106%

197%

LinkedList内部搜索

470%

493%

448%

表5:通过ListIterator遍历集合中的所有元素

 

1.2 JVM

1.3 JVM

HotSpot 2.0 JVM

利用ListIterator迭代ArrayList

100%

118%

75.2%

利用ListIterator迭代ListedList

117%

186%

156%

■ 结束语
实际测量和我们所考虑的其他因素都清楚地显示出,ArrayList和Vector通常比LinkedList和同步封装之后的LinkedList有着更好的性能。即使在你认为LinkedList可能提供更高性能的情况下,你也可以通过修改元素加入的方式从ArrayList争取更好的性能,例如翻转集合元素的次序。

有些情况下LinkedList会有更好的性能,例如,当大量元素需要同时加入到大型集合的开头和末尾时。但一般而言,我建议你优先使用ArrayList/Vector类,只有当它们存在明显的性能问题而LinkedList能够改进性能时,才使用LinkedList。

posted @ 2006-03-31 12:02 高山流水 阅读(70) | 评论 (0)编辑 收藏

Oracle优化经典文章------索引原理篇

Oracle提供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。这篇文章就将简单的讨论每个索引选项。主要有以下内容:

[1] 基本的索引概念
    查询DBA_INDEXES视图可得到表中所有索引的列表,注意只能通过USER_INDEXES的方法来检索模式(schema)的索引。访问USER_IND_COLUMNS视图可得到一个给定表中被索引的特定列。

[2] 组合索引
    当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在 Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。
    特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!

[3] ORACLE ROWID
    通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。   

[4] 限制索引
    限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:
   
    4.1 使用不等于操作符(<>、!=)
        下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。
         select cust_Id,cust_name
         from   customers
         where  cust_rating <> 'aa';
         把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。
         select cust_Id,cust_name
         from   customers
         where  cust_rating < 'aa' or cust_rating > 'aa';
     特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。
     
     4.2 使用IS NULL 或IS NOT NULL
         使用IS NULL 或IS NOT NULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开     发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索     引,关于位图索引在稍后在详细讨论)。

     4.3 使用函数
         如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。
         下面的查询不会使用索引(只要它不是基于函数的索引)
          select empno,ename,deptno
          from   emp
          where  trunc(hiredate)='01-MAY-81';
          把上面的语句改成下面的语句,这样就可以通过索引进行查找。
          select empno,ename,deptno
          from   emp
          where  hiredate<(to_date('01-MAY-81')+0.9999);

     4.4 比较不匹配的数据类型
         比较不匹配的数据类型也是比较难于发现的性能问题之一。
         注意下面查询的例子,account_number是一个VARCHAR2类型,在account_number字段上有索引。下面的语句将执行全表扫描。
         select bank_name,address,city,state,zip
         from   banks
         where  account_number = 990354;
         Oracle可以自动把where子句变成to_number(account_number)=990354,这样就限制了索引的使用,改成下面的查询就可以使用索引:
         select bank_name,address,city,state,zip
         from   banks
         where  account_number ='990354';
     特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,即便对这个查询执行Explain Plan也不能让您明白为什么做了一               次“全表扫描”。

[5] 选择性
    使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。

[6] 群集因子(Clustering Factor)
    Clustering Factor位于USER_INDEXES视图中。该列反映了数据相对于已索引的列是否显得有序。如果Clustering Factor列的值接近于索引中的树叶块(leaf block)的数目,表中的数据就越有序。如果它的值接近于表中的行数,则表中的数据就不是很有序。
   

[7] 二元高度(Binary height)
    索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B-level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。

[8] 快速全局扫描
    在Oracle7.3后就可以使用快速全局扫描(Fast Full Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。

[9] 跳跃式扫描
    从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。下面的程序清单显示出性能的差别:
    create index skip1 on emp5(job,empno);
    index created.

    select count(*)
    from emp5
    where empno=7900;

    Elapsed:00:00:03.13

    Execution Plan
    0     SELECT STATEMENT Optimizer=CHOOSE(Cost=4 Card=1 Bytes=5)
    1  0    SORT(AGGREGATE)
    2  1      INDEX(FAST FULL SCAN) OF 'SKIP1'(NON-UNIQUE)

    Statistics

    6826 consistent gets
    6819 physical   reads

    select /*+ index(emp5 skip1)*/ count(*)
    from emp5
    where empno=7900;

    Elapsed:00:00:00.56

    Execution Plan
    0     SELECT STATEMENT Optimizer=CHOOSE(Cost=6 Card=1 Bytes=5)
    1  0    SORT(AGGREGATE)
    2  1      INDEX(SKIP SCAN) OF 'SKIP1'(NON-UNIQUE)

    Statistics

    21 consistent gets
    17 physical   reads

[10] 索引的类型
     B-树索引
     位图索引
     HASH索引
     索引编排表
     反转键索引
     基于函数的索引
     分区索引
     本地和全局索引
     特别说明:关于这部分内容大家感兴趣可以自己查找资料学习!
http://www.cnoug.org/

posted @ 2006-03-31 12:02 高山流水 阅读(134) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 10 11 12 13 14 15 16 17 18 Last