隨筆 - 18, 文章 - 0, 評(píng)論 - 8, 引用 - 0
          數(shù)據(jù)加載中……

          2005年7月20日

          CyclicBarrier 簡(jiǎn)單舉例

          一句話(huà)解釋?zhuān)侯A(yù)備~~~開(kāi)始

           1 import java.util.concurrent.BrokenBarrierException;
           2 import java.util.concurrent.CyclicBarrier;
           3 
           4 import org.slf4j.Logger;
           5 import org.slf4j.LoggerFactory;
           6 
           7 public class CyclicBarrierLearn {
           8     
           9     private Logger log = LoggerFactory.getLogger(CyclicBarrierLearn.class);
          10     
          11     private class Work extends Thread {
          12         
          13         private String name;
          14         private CyclicBarrier cyclicBarrier;
          15         
          16         public Work(String name, CyclicBarrier cyclicBarrier) {
          17             this.name = name;
          18             this.cyclicBarrier = cyclicBarrier;
          19         }
          20         
          21         @Override
          22         public void run() {
          23             try {
          24                 log.debug("thread name: " + name + " waiting work");
          25                 cyclicBarrier.await();
          26                 log.debug("thread name: " + name + " working");
          27             } catch (InterruptedException e) {
          28                 e.printStackTrace();
          29             } catch (BrokenBarrierException e) {
          30                 e.printStackTrace();
          31             }
          32             
          33         }
          34     }
          35     
          36     public void cyclicBarrier() {
          37         CyclicBarrier cyclicBarrier = new CyclicBarrier(50, new Runnable() {
          38             
          39             @Override
          40             public void run() {
          41                 log.debug("let's begin work");
          42             }
          43         });
          44         
          45         for (int i = 0; i < cyclicBarrier.getParties(); i++) {
          46             Work work = new Work(String.valueOf(i), cyclicBarrier);
          47             work.start();
          48         }
          49         
          50     }
          51 
          52     public static void main(String[] args) {
          53         CyclicBarrierLearn cyclicBarrierLearn = new CyclicBarrierLearn();
          54         cyclicBarrierLearn.cyclicBarrier();
          55 
          56     }
          57 
          58 }
          59 

          posted @ 2017-07-13 11:39 丑男 閱讀(179) | 評(píng)論 (0)編輯 收藏

          CountDownLatch 簡(jiǎn)單舉例

          一句話(huà)解釋?zhuān)褐骶€程阻塞,其他線程完成后,主線程被喚醒后繼續(xù)執(zhí)行

           1 import java.util.Random;
           2 import java.util.concurrent.CountDownLatch;
           3 
           4 import org.slf4j.Logger;
           5 import org.slf4j.LoggerFactory;
           6 
           7 public class CountDownLatchLearn {
           8     
           9     private Logger log = LoggerFactory.getLogger(CountDownLatchLearn.class);
          10     private CountDownLatch countDownLatch;
          11     
          12     public CountDownLatchLearn() {
          13         countDownLatch = new CountDownLatch(50);
          14     }
          15     
          16     public void countDown() {
          17         Long count = countDownLatch.getCount();
          18         log.debug("countDownLatch count is:" + count.toString());
          19         
          20         for (int i = 0; i < count; i++) {
          21             Work work = new Work(String.valueOf(i), countDownLatch);
          22             work.start();
          23         }
          24         try {
          25             countDownLatch.await();
          26         } catch (InterruptedException e) {
          27             e.printStackTrace();
          28         }
          29         log.debug("work finish!!!");
          30     }
          31     
          32     private class Work extends Thread {
          33         
          34         private String name;
          35         private CountDownLatch countDownLatch;
          36         
          37         public Work(String name, CountDownLatch countDownLatch) {
          38             this.name = name;
          39             this.countDownLatch = countDownLatch;
          40         }
          41         
          42         @Override
          43         public void run() {
          44             Random r = new Random();
          45             int sleep = r.nextInt(2000);
          46             try {
          47                 log.debug("thread sleep: "+ sleep);
          48                 Thread.sleep(sleep);
          49             } catch (InterruptedException e) {
          50                 e.printStackTrace();
          51             }
          52             log.debug("thread: " + name + ": do work");
          53             countDownLatch.countDown();
          54         }
          55     }
          56 
          57     public static void main(String[] args) {
          58         System.out.println("main start!!!");
          59         
          60         CountDownLatchLearn countDownLatchLearn = new CountDownLatchLearn();
          61         countDownLatchLearn.countDown();
          62         
          63         System.out.println("main end!!!");
          64     }
          65 
          66 }

          posted @ 2017-07-13 11:18 丑男 閱讀(315) | 評(píng)論 (0)編輯 收藏

          mysql 5.7 for windows安裝過(guò)程

          環(huán)境說(shuō)明:

          OSwindows 7 64bit Databasemysql-5.7.18-winx64 Noinstall版本

           

          1. 解壓Mysql安裝目錄

          2. 編寫(xiě)my.ini配置文件

          3. mysqld --defaults-file=../my.ini --initialize

          4. ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

          5. mysql –u root –p

          6. 密碼在logs/*.err日志中

           
          my.ini文件內(nèi)容

           1 # my.ini文件內(nèi)容
           2 # For advice on how to change settings please see
           3 # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
           4 # *** DO NOT EDIT THIS FILE. It's a template which will be copied to the
           5 # *** default location during install, and will be replaced if you
           6 # *** upgrade to a newer version of MySQL.
           7 
           8 [mysqld]
           9 
          10 # Remove leading # and set to the amount of RAM for the most important data
          11 # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
          12 # innodb_buffer_pool_size = 128M
          13 
          14 # Remove leading # to turn on a very important data integrity option: logging
          15 # changes to the binary log between backups.
          16 # log_bin
          17 
          18 # These are commonly set, remove the # and set as required.
          19 basedir=D:\\mysql-5.7.18-winx64
          20 datadir=D:\\mysql-5.7.18-winx64\\data
          21 # port = ..
          22 # server_id = ..
          23 
          24 
          25 # Remove leading # to set options mainly useful for reporting servers.
          26 # The server defaults are faster for transactions and fast SELECTs.
          27 # Adjust sizes as needed, experiment to find the optimal values.
          28 # join_buffer_size = 128M
          29 # sort_buffer_size = 2M
          30 # read_rnd_buffer_size = 2M 
          31 
          32 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
          33 
          34 long_query_time=0.1
          35 slow_query_log=on
          36 slow_query_log_file=D:\\mysql-5.7.18-winx64\\logs\\mysqlslow.log
          37 

          posted @ 2017-07-10 00:53 丑男 閱讀(218) | 評(píng)論 (0)編輯 收藏

          添加用戶(hù)【備份】

          useradd -g 501 -s /sbin/nologin builder

          posted @ 2013-05-06 17:25 丑男 閱讀(130) | 評(píng)論 (0)編輯 收藏

          [ZT]Java虛擬機(jī)JVM的調(diào)優(yōu)參數(shù)選擇

          在任何一個(gè)的生產(chǎn)系統(tǒng)上線前,系統(tǒng)性能調(diào)優(yōu)(Tuning)都是很重要的一步。通常,應(yīng)用系統(tǒng)的軟硬件的缺省值都是給開(kāi)發(fā)平臺(tái)(或小規(guī)模系統(tǒng))設(shè)計(jì)的,用來(lái)跑生產(chǎn)系統(tǒng)幾乎都無(wú)法發(fā)揮出軟硬件的最佳性能。有時(shí),系統(tǒng)調(diào)優(yōu)前后的性能會(huì)差好幾倍。另一方面,由于應(yīng)用程序的開(kāi)發(fā)人員通常都是針對(duì)功能作開(kāi)發(fā)的,因此,開(kāi)發(fā)硬件都是比生產(chǎn)環(huán)境要小的機(jī)器。例如,生產(chǎn)系統(tǒng)是一臺(tái)8個(gè)CPU,64GB內(nèi)存服務(wù)器,而開(kāi)發(fā)服務(wù)器可能只有1個(gè)CPU和4GB內(nèi)存。所以,在開(kāi)發(fā)人員中常常不具備做性能方面測(cè)試的軟硬件環(huán)境。另外,有的程序員甚至在開(kāi)發(fā)時(shí)都沒(méi)有考慮到多用戶(hù)并發(fā)的環(huán)境,程序中存在單點(diǎn)瓶頸等問(wèn)題。在做壓力測(cè)試和調(diào)優(yōu)時(shí),往往就會(huì)發(fā)現(xiàn)這些關(guān)鍵點(diǎn)。

            由于應(yīng)用系統(tǒng)是個(gè)軟硬件的完整統(tǒng)一體,系統(tǒng)調(diào)優(yōu)往往需要涉及硬件、網(wǎng)絡(luò)操作系統(tǒng)、中間件,應(yīng)用程序和數(shù)據(jù)庫(kù)等方面。在調(diào)優(yōu)的過(guò)程中,往往需要發(fā)現(xiàn)存在瓶頸的地方(也就是導(dǎo)致系統(tǒng)變慢的部分),分析原因,從而改進(jìn)和確定較優(yōu)的參數(shù)。

            我們?cè)谧鱆VM的調(diào)優(yōu)前,通常先要了解運(yùn)行的硬件平臺(tái),操作系統(tǒng)和中間件,然后針對(duì)這些情況配置相應(yīng)的系統(tǒng)參數(shù),在測(cè)試中不斷完善參數(shù)。由于性能調(diào)優(yōu)需要對(duì)系統(tǒng)非常了解,并且需要豐富的經(jīng)驗(yàn),因此不是一件容易的事情。這里介紹一些很好的參考資料,就是SPEC.org的網(wǎng)站。這是硬件廠商公布benchmark測(cè)試結(jié)果的地方,通常硬件廠商會(huì)把系統(tǒng)調(diào)到最優(yōu)化才公布結(jié)果的,因此很有借鑒意義。常見(jiàn)和JVM有關(guān)的benchmark值主要有SPECjAppServer2004和SPECjbb2005。前者是J2EE應(yīng)用服務(wù)器的性能指標(biāo),后者是服務(wù)器端Java虛擬機(jī)的性能指標(biāo)。給大家介紹這個(gè)網(wǎng)站的目的是說(shuō)大家可以參考硬件廠商給出的JVM配置,在根據(jù)自己應(yīng)用環(huán)境的特點(diǎn),較快的得出較好的參數(shù)。例如,這個(gè)網(wǎng)頁(yè)給出了SUN公司T5120服務(wù)器+應(yīng)用服務(wù)器9.1 +JDK1.5的SPECjAppServer2004值是8,439.36:

            http://www.spec.org/jAppServer2004/results/res2007q4/jAppServer2004-20071106-00092.html

            我們現(xiàn)在要關(guān)心的不是Benchmark的值(注:實(shí)際上,Sun公司的這個(gè)值是個(gè)很不錯(cuò)的結(jié)果),而是留意在這種環(huán)境下JVM的參數(shù)配置,可以找到一個(gè)欄目“Notes / Tuning Information”:

            JVM Options: -server -XX:+AggressiveHeap

          -Xmx2560m -Xms2560m -Xmn1024m -Xss128k

          -XX:PermSize=256m

          -XX:+DisableExplicitGC

          -XX:ParallelGCThreads=24

          -XX:LargePageSizeInBytes=256m

          -XX:+UseParallelOldGC

          -XX:+AggressiveOpts

          -DAllowManagedFieldsInDefaultFetchGroup=true

          -DAllowMediatedWriteInDefaultFetchGroup=true

          -XX:-UseBiasedLocking

          -Dcom.sun.ejb.containers.readonly.relative.refresh.mode=true

          -Dcom.sun.jts.dblogging.insertquery=insert into

          txn_log_table_0 values (
          ? , ? , ? )

          -Dcom.sun.jts.dblogging.deletequery=delete from

          txn_log_table_0 where localtid
          = ? and servername = ?

          -Dcom.sun.jdo.spi.persistence.support.sqlstore.

          MULTILEVEL_PREFETCH
          =true

            那么上面那些參數(shù)是什么意思呢?上述段落中“-XX”的參數(shù)是SUN JVM的擴(kuò)展選項(xiàng),其中以下的這些都是和垃圾回收(GC)有關(guān):

            -XX:PermSize=256m

          -XX:+DisableExplicitGC

          -XX:ParallelGCThreads=24

          -XX:+UseParallelOldGC

          -XX:+AggressiveHeap

            下面這個(gè)選項(xiàng)是選擇大的內(nèi)存頁(yè)面:

            -XX:LargePageSizeInBytes=256m

            "-XX:+AggressiveOpts"是一些試驗(yàn)性?xún)?yōu)化參數(shù),“-XX:-UseBiasedLocking”是非競(jìng)爭(zhēng)性的同步選項(xiàng)。

            而選項(xiàng)“-Xmx2560m -Xms2560m -Xmn1024m -Xss128k”則是初始堆棧的內(nèi)存值,注意-Xmx和-Xms的值是一樣的,這樣系統(tǒng)性能會(huì)較平穩(wěn)些。

            至于這些參數(shù)詳細(xì)代表什么意義,大家可以google一下就很容易了解。這是Sun網(wǎng)站上的說(shuō)明,有興趣的可以讀一下: http://java.sun.com/performance/reference/whitepapers/tuning.html

            如果你的應(yīng)用系統(tǒng)是JDK1.5,硬件是T5120,操作系統(tǒng)是Solaris,那么這些參數(shù)就很有借鑒意義。如果你的硬件系統(tǒng)不是T5120,但是使用SUN的JDK1.5 ,這些參數(shù)也是有一定參考作用。當(dāng)然,最理想的是選擇一個(gè)和自己的環(huán)境最近似的結(jié)果來(lái)參考。大多數(shù)軟硬件的測(cè)試結(jié)果都可以在SPEC.org上找到,如果你的系統(tǒng)是J2EE的3層架構(gòu),可以用jAppServer2004指標(biāo),如果是純JAVA的應(yīng)用,可用jbb2005的結(jié)果:

            http://www.spec.org/jAppServer2004/

            http://www.spec.org/jbb2005/

            需要注意的是,這些調(diào)優(yōu)參數(shù)只是提供了一個(gè)思路,具體是否合適你的應(yīng)用還要看實(shí)測(cè)結(jié)果。

          posted @ 2009-04-29 19:24 丑男 閱讀(275) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)帖]Hibernate常用保存

          hibernate對(duì)于對(duì)象的保存提供了太多的方法,他們之間有很多不同,這里細(xì)說(shuō)一下,以便區(qū)別:
          一、預(yù)備知識(shí):
          在所有之前,說(shuō)明一下,對(duì)于hibernate,它的對(duì)象有三種狀態(tài),transient、persistent、detached
          下邊是常見(jiàn)的翻譯辦法:
          transient:瞬態(tài)或者自由態(tài)
          persistent:持久化狀態(tài)
          detached:脫管狀態(tài)或者游離態(tài)
          脫管狀態(tài)的實(shí)例可以通過(guò)調(diào)用save()、persist()或者saveOrUpdate()方法進(jìn)行持久化。
          持久化實(shí)例可以通過(guò)調(diào)用 delete()變成脫管狀態(tài)。通過(guò)get()或load()方法得到的實(shí)例都是持久化狀態(tài)的。
          脫管狀態(tài)的實(shí)例可以通過(guò)調(diào)用 update()、0saveOrUpdate()、lock()或者replicate()進(jìn)行持久化。
          save() 和persist()將會(huì)引發(fā)SQL的INSERT,delete()會(huì)引發(fā)SQLDELETE,而update()或merge()會(huì)引發(fā) SQLUPDATE.對(duì)持久化(persistent)實(shí)例的修改在刷新提交的時(shí)候會(huì)被檢測(cè)到,它也會(huì)引起 SQLUPDATE.saveOrUpdate()或者replicate()會(huì)引發(fā)SQLINSERT或者UPDATE
          二、save 和update區(qū)別
          把這一對(duì)放在第一位的原因是因?yàn)檫@一對(duì)是最常用的。
          save的作用是把一個(gè)新的對(duì)象保存
          update是把一個(gè)脫管狀態(tài)的對(duì)象保存
          三、update 和saveOrUpdate區(qū)別
          這個(gè)是比較好理解的,顧名思義,saveOrUpdate基本上就是合成了save和update引用hibernate reference中的一段話(huà)來(lái)解釋他們的使用場(chǎng)合和區(qū)別。
          通常下面的場(chǎng)景會(huì)使用update()或saveOrUpdate():
          程序在第一個(gè)session中加載對(duì)象
          該對(duì)象被傳遞到表現(xiàn)層
          對(duì)象發(fā)生了一些改動(dòng)
          該對(duì)象被返回到業(yè)務(wù)邏輯層
          程序調(diào)用第二個(gè)session的update()方法持久這些改動(dòng)
          saveOrUpdate()做下面的事:
          如果對(duì)象已經(jīng)在本session中持久化了,不做任何事
          如果另一個(gè)與本session關(guān)聯(lián)的對(duì)象擁有相同的持久化標(biāo)識(shí)(identifier),拋出一個(gè)異常
          如果對(duì)象沒(méi)有持久化標(biāo)識(shí)(identifier)屬性,對(duì)其調(diào)用save()
          如果對(duì)象的持久標(biāo)識(shí)(identifier)表明其是一個(gè)新實(shí)例化的對(duì)象,對(duì)其調(diào)用save()
          如果對(duì)象是附帶版本信息的(通過(guò)或) 并且版本屬性的值表明其是一個(gè)新實(shí)例化的對(duì)象,save()它。
          四、persist和save區(qū)別
          這個(gè)是最迷離的一對(duì),表面上看起來(lái)使用哪個(gè)都行,在hibernate reference文檔中也沒(méi)有明確的區(qū)分他們。
          這里給出一個(gè)明確的區(qū)分。(可以跟進(jìn)src看一下,雖然實(shí)現(xiàn)步驟類(lèi)似,但是還是有細(xì)微的差別)
          1.persist把一個(gè)瞬態(tài)的實(shí)例持久化,但是并"不保證"標(biāo)識(shí)符被立刻填入到持久化實(shí)例中,標(biāo)識(shí)符的填入可能被推遲到flush的時(shí)間。
          2.persist" 保證",當(dāng)它在一個(gè)transaction外部被調(diào)用的時(shí)候并不觸發(fā)一個(gè)Sql Insert,這個(gè)功能是很有用的,當(dāng)我們通過(guò)繼承Session/persistence context來(lái)封裝一個(gè)長(zhǎng)會(huì)話(huà)流程的時(shí)候,一個(gè)persist這樣的函數(shù)是需要的。
          3.save"不保證"第2條,它要返回標(biāo)識(shí)符,所以它會(huì)立即執(zhí)行Sql insert,不管是不是在transaction內(nèi)部。
          五、saveOrUpdateCopy,merge和update區(qū)別
          首先說(shuō)明merge是用來(lái)代替saveOrUpdateCopy的,然后比較update和merge,update的作用上邊說(shuō)了,這里說(shuō)一下merge的作用。
          如果session中存在相同持久化標(biāo)識(shí)(identifier)的實(shí)例,用用戶(hù)給出的對(duì)象的狀態(tài)覆蓋舊有的持久實(shí)例
          如果session沒(méi)有相應(yīng)的持久實(shí)例,則嘗試從數(shù)據(jù)庫(kù)中加載,或創(chuàng)建新的持久化實(shí)例,最后返回該持久實(shí)例
          用戶(hù)給出的這個(gè)對(duì)象沒(méi)有被關(guān)聯(lián)到session上,它依舊是脫管的
          重點(diǎn)是最后一句:
          當(dāng)我們使用update的時(shí)候,執(zhí)行完成后,我們提供的對(duì)象A的狀態(tài)變成持久化狀態(tài)
          但當(dāng)我們使用merge的時(shí)候,執(zhí)行完成,我們提供的對(duì)象A還是脫管狀態(tài),hibernate或者new了一個(gè)B,或者檢索到一個(gè)持久對(duì)象,并把我們提供的對(duì)象A的所有的值拷貝到這個(gè)B,執(zhí)行完成后B是持久狀態(tài),而我們提供的A還是托管狀態(tài)。
          六、flush和update區(qū)別
          這兩個(gè)的區(qū)別好理解
          update操作的是在脫管狀態(tài)的對(duì)象,而flush是操作的在持久狀態(tài)的對(duì)象。
          默認(rèn)情況下,一個(gè)持久狀態(tài)的對(duì)象是不需要update的,只要你更改了對(duì)象的值,等待hibernate flush就自動(dòng)保存到數(shù)據(jù)庫(kù)了。hibernate flush發(fā)生再幾種情況下:
          1.調(diào)用某些查詢(xún)的時(shí)候
          2.transaction commit的時(shí)候
          3.手動(dòng)調(diào)用flush的時(shí)候
          七、lock和update區(qū)別
          update是把一個(gè)已經(jīng)更改過(guò)的脫管狀態(tài)的對(duì)象變成持久狀態(tài)
          lock是把一個(gè)沒(méi)有更改過(guò)的脫管狀態(tài)的對(duì)象變成持久狀態(tài)
          對(duì)應(yīng)更改一個(gè)記錄的內(nèi)容,兩個(gè)的操作不同:
          update的操作步驟是:
          更改脫管的對(duì)象->調(diào)用update
          lock的操作步驟是:
          調(diào)用lock把對(duì)象從脫管狀態(tài)變成持久狀態(tài)——>更改持久狀態(tài)的對(duì)象的內(nèi)容——>等待flush或者手動(dòng)flush

          posted @ 2008-08-23 21:22 丑男 閱讀(250) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)帖]Oracle執(zhí)行計(jì)劃解釋

          一.相關(guān)的概念

              Rowid的概念:rowid是一個(gè)偽列,既然是偽列,那么這個(gè)列就不是用戶(hù)定義,而是系統(tǒng)自己給加上的。 對(duì)每個(gè)表都有一個(gè)rowid的偽列,但是表中并不物理存儲(chǔ)ROWID列的值。不過(guò)你可以像使用其它列那樣使用它,但是不能刪除改列,也不能對(duì)該列的值進(jìn)行 修改、插入。一旦一行數(shù)據(jù)插入數(shù)據(jù)庫(kù),則rowid在該行的生命周期內(nèi)是唯一的,即即使該行產(chǎn)生行遷移,行的rowid也不會(huì)改變。

              Recursive SQL概念:有時(shí)為了執(zhí)行用戶(hù)發(fā)出的一個(gè)sql語(yǔ)句,oracle必須執(zhí)行一些額外的語(yǔ)句,我們將這些額外的語(yǔ)句稱(chēng)之為''recursive calls''或''recursive sql statements''.如當(dāng)一個(gè)DDL語(yǔ)句發(fā)出后,ORACLE總是隱含的發(fā)出一些recursive SQL語(yǔ)句,來(lái)修改數(shù)據(jù)字典信息,以便用戶(hù)可以成功的執(zhí)行該DDL語(yǔ)句。當(dāng)需要的數(shù)據(jù)字典信息沒(méi)有在共享內(nèi)存中時(shí),經(jīng)常會(huì)發(fā)生Recursive calls,這些Recursive calls會(huì)將數(shù)據(jù)字典信息從硬盤(pán)讀入內(nèi)存中。用戶(hù)不比關(guān)心這些recursive SQL語(yǔ)句的執(zhí)行情況,在需要的時(shí)候,ORACLE會(huì)自動(dòng)的在內(nèi)部執(zhí)行這些語(yǔ)句。當(dāng)然DML語(yǔ)句與SELECT都可能引起recursive sql.簡(jiǎn)單的說(shuō),我們可以將觸發(fā)器視為recursive sql.

              Row Source(行源):用在查詢(xún)中,由上一操作返回的符合條件的行的集合,即可以是表的全部行數(shù)據(jù)的集合;也可以是表的部分行數(shù)據(jù)的集合;也可以為對(duì)上2個(gè)row source進(jìn)行連接操作(如join連接)后得到的行數(shù)據(jù)集合。

              Predicate(謂詞):一個(gè)查詢(xún)中的WHERE限制條件

              Driving table(驅(qū)動(dòng)表):該表又稱(chēng)為外層表(OUTER table)。 這個(gè)概念用于嵌套與HASH連接中。如果該row source返回較多的行數(shù)據(jù),則對(duì)所有的后續(xù)操作有負(fù)面影響。注意此處雖然翻譯為驅(qū)動(dòng)表,但實(shí)際上翻譯為驅(qū)動(dòng)行源(driving row source)更為確切。一般說(shuō)來(lái),是應(yīng)用查詢(xún)的限制條件后,返回較少行源的表作為驅(qū)動(dòng)表,所以如果一個(gè)大表在WHERE條件有有限制條件(如等值限 制),則該大表作為驅(qū)動(dòng)表也是合適的,所以并不是只有較小的表可以作為驅(qū)動(dòng)表,正確說(shuō)法應(yīng)該為應(yīng)用查詢(xún)的限制條件后,返回較少行源的表作為驅(qū)動(dòng)表。在執(zhí)行 計(jì)劃中,應(yīng)該為靠上的那個(gè)row source,后面會(huì)給出具體說(shuō)明。在我們后面的描述中,一般將該表稱(chēng)為連接操作的row source 1.

              Probed table(被探查表):該表又稱(chēng)為內(nèi)層表(INNER table)。在我們從驅(qū)動(dòng)表中得到具體一行的數(shù)據(jù)后,在該表中尋找符合連接條件的行。所以該表應(yīng)當(dāng)為大表(實(shí)際上應(yīng)該為返回較大row source的表)且相應(yīng)的列上應(yīng)該有索引。在我們后面的描述中,一般將該表稱(chēng)為連接操作的row source 2.

              組合索引(concatenated index):由多個(gè)列構(gòu)成的索引,如create index idx_emp on emp(col1, col2, col3, ……),則我們稱(chēng)idx_emp索引為組合索引。在組合索引中有一個(gè)重要的概念:引導(dǎo)列(leading column),在上面的例子中,col1列為引導(dǎo)列。當(dāng)我們進(jìn)行查詢(xún)時(shí)可以使用“where col1 = ? ”,也可以使用“where col1 = ? and col2 = ?”,這樣的限制條件都會(huì)使用索引,但是“where col2 = ? ”查詢(xún)就不會(huì)使用該索引。所以限制條件中包含先導(dǎo)列時(shí),該限制條件才會(huì)使用該組合索引。

              可選擇性(selectivity):比較一下列中唯一鍵的數(shù)量和表中的行數(shù),就可以判斷該列的可選擇性。 如果該列的“唯一鍵的數(shù)量/表中的行數(shù)”的比值越接近1,則該列的可選擇性越高,該列就越適合創(chuàng)建索引,同樣索引的可選擇性也越高。在可選擇性高的列上進(jìn) 行查詢(xún)時(shí),返回的數(shù)據(jù)就較少,比較適合使用索引查詢(xún)。

          歡迎進(jìn)入Oracle社區(qū)論壇,與200萬(wàn)技術(shù)人員互動(dòng)交流 >>進(jìn)入
          二.oracle訪問(wèn)數(shù)據(jù)的存取方法

              1) 全表掃描(Full table Scans, FTS)

              為實(shí)現(xiàn)全表掃描,oracle讀 取表中所有的行,并檢查每一行是否滿(mǎn)足語(yǔ)句的WHERE限制條件一個(gè)多塊讀 操作可以使一次I/O能讀取多塊數(shù)據(jù)塊(db_block_multiblock_read_count參數(shù)設(shè)定),而不是只讀取一個(gè)數(shù)據(jù)塊,這極大的減 少了I/O總次數(shù),提高了系統(tǒng)的吞吐量,所以利用多塊讀的方法可以十分高效地實(shí)現(xiàn)全表掃描,而且只有在全表掃描的情況下才能使用多塊讀操作。在這種訪問(wèn)模 式下,每個(gè)數(shù)據(jù)塊只被讀一次。

              使用FTS的前提條件:在較大的表上不建議使用全表掃描,除非取出數(shù)據(jù)的比較多,超過(guò)總量的5% —— 10%,或你想使用并行查詢(xún)功能時(shí)。

              使用全表掃描的例子:

              ~~~~~~~~~~~~~~~~~~~~~~~~ sql> explain plan for select * from dual;

              Query Plan

              -----------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=

              table ACCESS FULL DUAL

              2) 通過(guò)ROWID的表存取(Table Access by ROWID或rowid lookup)

              行的ROWID指出了該行所在的數(shù)據(jù)文件、數(shù)據(jù)塊以及行在該塊中的位置,所以通過(guò)ROWID來(lái)存取數(shù)據(jù)可以快速定位到目標(biāo)數(shù)據(jù)上,是Oracle存取單行數(shù)據(jù)的最快方法。

              這種存取方法不會(huì)用到多塊讀操作,一次I/O只能讀取一個(gè)數(shù)據(jù)塊。我們會(huì)經(jīng)常在執(zhí)行計(jì)劃中看到該存取方法,如通過(guò)索引查詢(xún)數(shù)據(jù)。

              使用ROWID存取的方法: sql> explain plan for select * from dept where rowid = ''AAAAyGAADAAAAATAAF'';

              Query Plan

              ------------------------------------

              SELECT STATEMENT [CHOOSE] Cost=1

              table ACCESS BY ROWID DEPT [ANALYZED]


              3)索引掃描(Index Scan或index lookup)

              我們先通過(guò)index查找到數(shù)據(jù)對(duì)應(yīng)的rowid值(對(duì)于非唯一索引可能返回多個(gè)rowid值),然后根據(jù)rowid直接從表中得到具體的數(shù)據(jù),這 種查找方式稱(chēng)為索引掃描或索引查找(index lookup)。一個(gè)rowid唯一的表示一行數(shù)據(jù),該行對(duì)應(yīng)的數(shù)據(jù)塊是通過(guò)一次i/o得到的,在此情況下該次i/o只會(huì)讀取一個(gè)數(shù)據(jù)庫(kù)塊。

              在索引中,除了存儲(chǔ)每個(gè)索引的值外,索引還存儲(chǔ)具有此值 的行對(duì)應(yīng)的ROWID值。索引掃描可以由2步組成:(1) 掃描索引得到對(duì)應(yīng)的rowid值。 (2) 通過(guò)找到的rowid從表中讀出具體的數(shù)據(jù)。每步都是單獨(dú)的一次I/O,但是對(duì)于索引,由于經(jīng)常使用,絕大多數(shù)都已經(jīng)CACHE到內(nèi)存中,所以第1步的 I/O經(jīng)常是邏輯I/O,即數(shù)據(jù)可以從內(nèi)存中得到。但是對(duì)于第2步來(lái)說(shuō),如果表比較大,則其數(shù)據(jù)不可能全在內(nèi)存中,所以其I/O很有可能是物理I/O,這 是一個(gè)機(jī)械操作,相對(duì)邏輯I/O來(lái)說(shuō),是極其費(fèi)時(shí)間的。所以如果多大表進(jìn)行索引掃描,取出的數(shù)據(jù)如果大于總量的5% —— 10%,使用索引掃描會(huì)效率下降很多。如下列所示:SQL> explain plan for select empno, ename from emp where empno=10;

              Query Plan

              ------------------------------------

              SELECT STATEMENT [CHOOSE] Cost=1

              table ACCESS BY ROWID EMP [ANALYZED]

              INDEX UNIQUE SCAN EMP_I1


              但是如果查詢(xún)的數(shù)據(jù)能全在索引中找到,就可以避免進(jìn)行第2步操作,避免了不必要的I/O,此時(shí)即使通過(guò)索引掃描取出的數(shù)據(jù)比較多,效率還是很高的

              sql> explain plan for select empno from emp where empno=10;-- 只查詢(xún)empno列值

              Query Plan

              ------------------------------------

              SELECT STATEMENT [CHOOSE] Cost=1

              INDEX UNIQUE SCAN EMP_I1

              進(jìn)一步講,如果sql語(yǔ)句中對(duì)索引列進(jìn)行排序,因?yàn)樗饕呀?jīng)預(yù)先排序好了,所以在執(zhí)行計(jì)劃中不需要再對(duì)索引列進(jìn)行排序
              sql> explain plan for select empno, ename from emp

              where empno > 7876 order by empno;

              Query Plan

              --------------------------------------------------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=1

              table ACCESS BY ROWID EMP [ANALYZED]

              INDEX RANGE SCAN EMP_I1 [ANALYZED]


              從這個(gè)例子中可以看到:因?yàn)樗饕且呀?jīng)排序了的,所以將按照索引的順序查詢(xún)出符合條件的行,因此避免了進(jìn)一步排序操作。

          根據(jù)索引的類(lèi)型與where限制條件的不同,有4種類(lèi)型的索引掃描:

              索引唯一掃描(index unique scan)

              索引范圍掃描(index range scan)

              索引全掃描(index full scan)

              索引快速掃描(index fast full scan)

              (1) 索引唯一掃描(index unique scan)

              通過(guò)唯一索引查找一個(gè)數(shù)值經(jīng)常返回單個(gè)ROWID.如果存在UNIQUE 或PRIMARY KEY 約束(它保證了語(yǔ)句只存取單行)的話(huà),Oracle經(jīng)常實(shí)現(xiàn)唯一性?huà)呙琛?/p>

              使用唯一性約束的例子:

              sql> explain plan for

              select empno,ename from emp where empno=10;

              Query Plan

          ------------------------------------

              SELECT STATEMENT [CHOOSE] Cost=1

              table ACCESS BY ROWID EMP [ANALYZED]

              INDEX UNIQUE SCAN EMP_I1

              (2) 索引范圍掃描(index range scan)

              使用一個(gè)索引存取多行數(shù)據(jù),在唯一索引上使用索引范圍掃描的典型情況下是在謂詞(where限制條件)中使用了范圍操作符(如>、<、<>、>=、<=、between)

              使用索引范圍掃描的例子:

              sql> explain plan for select empno,ename from emp

              where empno > 7876 order by empno;

              Query Plan

          --------------------------------------------------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=1

              table ACCESS BY ROWID EMP [ANALYZED]

              INDEX RANGE SCAN EMP_I1 [ANALYZED]

              在非唯一索引上,謂詞col = 5可能返回多行數(shù)據(jù),所以在非唯一索引上都使用索引范圍掃描。

              使用index rang scan的3種情況:

              (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)

              (b) 在組合索引上,只使用部分列進(jìn)行查詢(xún),導(dǎo)致查詢(xún)出多行

              (c) 對(duì)非唯一索引列上進(jìn)行的任何查詢(xún)。

              (3) 索引全掃描(index full scan)

              與全表掃描對(duì)應(yīng),也有相應(yīng)的全索引掃描。而且此時(shí)查詢(xún)出的數(shù)據(jù)都必須從索引中可以直接得到。

              全索引掃描的例子:

              An Index full scan will not perform single block i/o''s and so it may prove to be inefficient.

              e.g.

              Index BE_IX is a concatenated index on big_emp (empno, ename)

              sql> explain plan for select empno, ename from big_emp order by empno,ename;

              Query Plan

          --------------------------------------------------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=26

              INDEX FULL SCAN BE_IX [ANALYZED]

              (4) 索引快速掃描(index fast full scan)

              掃描索引中的所有的數(shù)據(jù)塊,與 index full scan很類(lèi)似,但是一個(gè)顯著的區(qū)別就是它不對(duì)查詢(xún)出的數(shù)據(jù)進(jìn)行排序,即數(shù)據(jù)不是以排序順序被返回。在這種存取方法中,可以使用多塊讀功能,也可以使用并行讀入,以便獲得最大吞吐量與縮短執(zhí)行時(shí)間。

              索引快速掃描的例子:

              BE_IX索引是一個(gè)多列索引: big_emp (empno,ename)

              sql> explain plan for select empno,ename from big_emp;

              Query Plan

          ------------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=1

              INDEX FAST FULL SCAN BE_IX [ANALYZED]

              只選擇多列索引的第2列:

              sql> explain plan for select ename from big_emp;

              Query Plan

          ------------------------------------------

              SELECT STATEMENT[CHOOSE] Cost=1

              INDEX FAST FULL SCAN BE_IX [ANALYZED]

             三、表之間的連接

              Join是一種試圖將兩個(gè)表結(jié)合在一起的謂詞,一次只能連接2個(gè)表,表連接也可以被稱(chēng)為表關(guān)聯(lián)。在后面的敘 述中,我們將會(huì)使用“row source”來(lái)代替“表”,因?yàn)槭褂胷ow source更嚴(yán)謹(jǐn)一些,并且將參與連接的2個(gè)row source分別稱(chēng)為row source1和row source 2.Join過(guò)程的各個(gè)步驟經(jīng)常是串行操作,即使相關(guān)的row source可以被并行訪問(wèn),即可以并行的讀取做join連接的兩個(gè)row source的數(shù)據(jù),但是在將表中符合限制條件的數(shù)據(jù)讀入到內(nèi)存形成row source后,join的其它步驟一般是串行的。有多種方法可以將2個(gè)表連接起來(lái),當(dāng)然每種方法都有自己的優(yōu)缺點(diǎn),每種連接類(lèi)型只有在特定的條件下才會(huì) 發(fā)揮出其最大優(yōu)勢(shì)。

              row source(表)之間的連接順序?qū)τ诓樵?xún)的效率有非常大的影響。通過(guò)首先存取特定的表,即將該表作為驅(qū)動(dòng)表,這樣可以先應(yīng)用某些限制條件,從而得到一個(gè) 較小的row source,使連接的效率較高,這也就是我們常說(shuō)的要先執(zhí)行限制條件的原因。一般是在將表讀入內(nèi)存時(shí),應(yīng)用where子句中對(duì)該表的限制條件。

              根據(jù)2個(gè)row source的連接條件的中操作符的不同,可以將連接分為等值連接(如WHERE A.COL3 = B.COL4)、非等值連接(WHERE A.COL3 > B.COL4)、外連接(WHERE A.COL3 = B.COL4(+))。上面的各個(gè)連接的連接原理都基本一樣,所以為了簡(jiǎn)單期間,下面以等值連接為例進(jìn)行介紹。

              在后面的介紹中,都已:

              SELECT A.COL1, B.COL2

              FROM A, B

              WHERE A.COL3 = B.COL4;

              為例進(jìn)行說(shuō)明,假設(shè)A表為Row Soruce1,則其對(duì)應(yīng)的連接操作關(guān)聯(lián)列為COL 3;B表為Row Soruce2,則其對(duì)應(yīng)的連接操作關(guān)聯(lián)列為COL 4;

              連接類(lèi)型:

              目前為止,無(wú)論連接操作符如何,典型的連接類(lèi)型共有3種:

              排序 - - 合并連接(Sort Merge Join (SMJ) )

              嵌套循環(huán)(Nested Loops (NL) )

              哈希連接(Hash Join)

              排序 - - 合并連接(Sort Merge Join, SMJ)

              內(nèi)部連接過(guò)程:

              1) 首先生成row source1需要的數(shù)據(jù),然后對(duì)這些數(shù)據(jù)按照連接操作關(guān)聯(lián)列(如A.col3)進(jìn)行排序。

              2) 隨后生成row source2需要的數(shù)據(jù),然后對(duì)這些數(shù)據(jù)按照與sort source1對(duì)應(yīng)的連接操作關(guān)聯(lián)列(如B.col4)進(jìn)行排序。

              3) 最后兩邊已排序的行被放在一起執(zhí)行合并操作,即將2個(gè)row source按照連接條件連接起來(lái)

              下面是連接步驟的圖形表示:

              MERGE

              /"

              SORTSORT

              ||

              Row Source 1Row Source 2

              如果row source已經(jīng)在連接關(guān)聯(lián)列上被排序,則該連接操作就不需要再進(jìn)行sort操作,這樣可以大大提高這種連接操作的連接速度,因?yàn)榕判蚴莻€(gè)極其費(fèi)資源的操 作,特別是對(duì)于較大的表。預(yù)先排序的row source包括已經(jīng)被索引的列(如a.col3或b.col4上有索引)或row source已經(jīng)在前面的步驟中被排序了。盡管合并兩個(gè)row source的過(guò)程是串行的,但是可以并行訪問(wèn)這兩個(gè)row source(如并行讀入數(shù)據(jù),并行排序)。

              SMJ連接的例子:SQL> explain plan for

              select /*+ ordered */ e.deptno, d.deptno

              from emp e, dept d

              where e.deptno = d.deptno

              order by e.deptno, d.deptno;

              Query Plan

          -------------------------------------

              SELECT STATEMENT [CHOOSE] Cost=17

              MERGE JOIN

              SORT JOIN

              table ACCESS FULL EMP [ANALYZED]

              SORT JOIN

              table ACCESS FULL DEPT [ANALYZED]


              排序是一個(gè)費(fèi)時(shí)、費(fèi)資源的操作,特別對(duì)于大表。基于這個(gè)原因,SMJ經(jīng)常不是一個(gè)特別有效的連接方法,但是如果2個(gè)row source都已經(jīng)預(yù)先排序,則這種連接方法的效率也是蠻高的。

              嵌套循環(huán)(Nested Loops, NL)

              這個(gè)連接方法有驅(qū)動(dòng)表(外部表)的概念。其實(shí),該連接過(guò)程就是一個(gè)2層嵌套循環(huán),所以外層循環(huán)的次數(shù)越少越好,這也就是我們?yōu)槭裁磳⑿”砘蚍祷剌^小 row source的表作為驅(qū)動(dòng)表(用于外層循環(huán))的理論依據(jù)。但是這個(gè)理論只是一般指導(dǎo)原則,因?yàn)樽裱@個(gè)理論并不能總保證使語(yǔ)句產(chǎn)生的I/O次數(shù)最少。有時(shí) 不遵守這個(gè)理論依據(jù),反而會(huì)獲得更好的效率。如果使用這種方法,決定使用哪個(gè)表作為驅(qū)動(dòng)表很重要。有時(shí)如果驅(qū)動(dòng)表選擇不正確,將會(huì)導(dǎo)致語(yǔ)句的性能很差、很 差。

              內(nèi)部連接過(guò)程:

              Row source1的Row 1 —— Probe ->Row source 2

              Row source1的Row 2 —— Probe ->Row source 2

              Row source1的Row 3 —— Probe ->Row source 2

              ……。

              Row source1的Row n —— Probe ->Row source 2

              從內(nèi)部連接過(guò)程來(lái)看,需要用row source1中的每一行,去匹配row source2中的所有行,所以此時(shí)保持row source1盡可能的小與高效的訪問(wèn)row source2(一般通過(guò)索引實(shí)現(xiàn))是影響這個(gè)連接效率的關(guān)鍵問(wèn)題。這只是理論指導(dǎo)原則,目的是使整個(gè)連接操作產(chǎn)生最少的物理I/O次數(shù),而且如果遵守這 個(gè)原則,一般也會(huì)使總的物理I/O數(shù)最少。但是如果不遵從這個(gè)指導(dǎo)原則,反而能用更少的物理I/O實(shí)現(xiàn)連接操作,那盡管違反指導(dǎo)原則吧!因?yàn)樽钌俚奈锢? I/O次數(shù)才是我們應(yīng)該遵從的真正的指導(dǎo)原則,在后面的具體案例分析中就給出這樣的例子。

              在上面的連接過(guò)程中,我們稱(chēng)Row source1為驅(qū)動(dòng)表或外部表。Row Source2被稱(chēng)為被探查表或內(nèi)部表。

              在NESTED LOOPS連接中,Oracle讀取row source1中的每一行,然后在row sourc2中檢查是否有匹配的行,所有被匹配的行都被放到結(jié)果集中,然后處理row source1中的下一行。這個(gè)過(guò)程一直繼續(xù),直到row source1中的所有行都被處理。這是從連接操作中可以得到第一個(gè)匹配行的最快的方法之一,這種類(lèi)型的連接可以用在需要快速響應(yīng)的語(yǔ)句中,以響應(yīng)速度為 主要目標(biāo)。

              如果driving row source(外部表)比較小,并且在inner row source(內(nèi)部表)上有唯一索引,或有高選擇性非唯一索引時(shí),使用這種方法可以得到較好的效率。NESTED LOOPS有其它連接方法沒(méi)有的的一個(gè)優(yōu)點(diǎn)是:可以先返回已經(jīng)連接的行,而不必等待所有的連接操作處理完才返回?cái)?shù)據(jù),這可以實(shí)現(xiàn)快速的響應(yīng)時(shí)間。

              如果不使用并行操作,最好的驅(qū)動(dòng)表是那些應(yīng)用了where 限制條件后,可以返回較少行數(shù)據(jù)的的表,所以大表也可能稱(chēng)為驅(qū)動(dòng)表,關(guān)鍵看限制條件。對(duì)于并行查詢(xún),我們經(jīng)常選擇大表作為驅(qū)動(dòng)表,因?yàn)榇蟊砜梢猿浞掷貌? 行功能。當(dāng)然,有時(shí)對(duì)查詢(xún)使用并行操作并不一定會(huì)比查詢(xún)不使用并行操作效率高,因?yàn)樽詈罂赡苊總€(gè)表只有很少的行符合限制條件,而且還要看你的硬件配置是否 可以支持并行(如是否有多個(gè)CPU,多個(gè)硬盤(pán)控制器),所以要具體問(wèn)題具體對(duì)待。

              NL連接的例子:

              sql> explain plan for

              select a.dname,b.sql

              from dept a,emp b

              where a.deptno = b.deptno;

              Query Plan

          -------------------------

              SELECT STATEMENT [CHOOSE] Cost=5

              NESTED LOOPS

              table ACCESS FULL DEPT [ANALYZED]

              table ACCESS FULL EMP [ANALYZED]


              哈希連接(Hash Join, HJ)

              這種連接是在oracle 7.3以后引入的,從理論上來(lái)說(shuō)比NL與SMJ更高效,而且只用在CBO優(yōu)化器中。

              較小的row source被用來(lái)構(gòu)建hash table與bitmap,第2個(gè)row source被用來(lái)被hansed,并與第一個(gè)row source生成的hash table進(jìn)行匹配,以便進(jìn)行進(jìn)一步的連接。Bitmap被用來(lái)作為一種比較快的查找方法,來(lái)檢查在hash table中是否有匹配的行。特別的,當(dāng)hash table比較大而不能全部容納在內(nèi)存中時(shí),這種查找方法更為有用。這種連接方法也有NL連接中所謂的驅(qū)動(dòng)表的概念,被構(gòu)建為hash table與bitmap的表為驅(qū)動(dòng)表,當(dāng)被構(gòu)建的hash table與bitmap能被容納在內(nèi)存中時(shí),這種連接方式的效率極高。

              HASH連接的例子:

              sql> explain plan for

              select /*+ use_hash(emp) */ empno

              from emp, dept

              where emp.deptno = dept.deptno;

              Query Plan

          ----------------------------

              SELECT STATEMENT[CHOOSE] Cost=3

              HASH JOIN

              table ACCESS FULL DEPT

              table ACCESS FULL EMP


              要使哈希連接有效,需要設(shè)置HASH_JOIN_ENABLED=TRUE,缺省情況下該參數(shù)為T(mén)RUE,另外,不要忘了還要設(shè)置 hash_area_size參數(shù),以使哈希連接高效運(yùn)行,因?yàn)楣_B接會(huì)在該參數(shù)指定大小的內(nèi)存中運(yùn)行,過(guò)小的參數(shù)會(huì)使哈希連接的性能比其他連接方式還 要低。

              總結(jié)一下,在哪種情況下用哪種連接方法比較好:

              排序 - - 合并連接(Sort Merge Join, SMJ):

              a) 對(duì)于非等值連接,這種連接方式的效率是比較高的。

              b) 如果在關(guān)聯(lián)的列上都有索引,效果更好。

              c) 對(duì)于將2個(gè)較大的row source做連接,該連接方法比NL連接要好一些。

              d) 但是如果sort merge返回的row source過(guò)大,則又會(huì)導(dǎo)致使用過(guò)多的rowid在表中查詢(xún)數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)性能下降,因?yàn)檫^(guò)多的I/O.

              嵌套循環(huán)(Nested Loops, NL):

              a) 如果driving row source(外部表)比較小,并且在inner row source(內(nèi)部表)上有唯一索引,或有高選擇性非唯一索引時(shí),使用這種方法可以得到較好的效率。

              b) NESTED LOOPS有其它連接方法沒(méi)有的的一個(gè)優(yōu)點(diǎn)是:可以先返回已經(jīng)連接的行,而不必等待所有的連接操作處理完才返回?cái)?shù)據(jù),這可以實(shí)現(xiàn)快速的響應(yīng)時(shí)間。

              哈希連接(Hash Join, HJ):

              a) 這種方法是在oracle7后來(lái)引入的,使用了比較先進(jìn)的連接理論,一般來(lái)說(shuō),其效率應(yīng)該好于其它2種連接,但是這種連接只能用在CBO優(yōu)化器中,而且需要設(shè)置合適的hash_area_size參數(shù),才能取得較好的性能。

              b) 在2個(gè)較大的row source之間連接時(shí)會(huì)取得相對(duì)較好的效率,在一個(gè)row source較小時(shí)則能取得更好的效率。

              c) 只能用于等值連接中

              笛卡兒乘積(Cartesian Product)

              當(dāng)兩個(gè)row source做連接,但是它們之間沒(méi)有關(guān)聯(lián)條件時(shí),就會(huì)在兩個(gè)row source中做笛卡兒乘積,這通常由編寫(xiě)代碼疏漏造成(即程序員忘了寫(xiě)關(guān)聯(lián)條件)。笛卡爾乘積是一個(gè)表的每一行依次與另一個(gè)表中的所有行匹配。在特殊情 況下我們可以使用笛卡兒乘積,如在星形連接中,除此之外,我們要盡量使用笛卡兒乘積,否則,自己想結(jié)果是什么吧!

              注意在下面的語(yǔ)句中,在2個(gè)表之間沒(méi)有連接。

              sql> explain plan for

              select emp.deptno,dept,deptno

              from emp,dept

              Query Plan

          ------------------------

              SLECT STATEMENT [CHOOSE] Cost=5

              MERGE JOIN CARTESIAN

              table ACCESS FULL DEPT

              SORT JOIN

              table ACCESS FULL EMP

              CARTESIAN關(guān)鍵字指出了在2個(gè)表之間做笛卡爾乘積。假如表emp有n行,dept表有m行,笛卡爾乘積的結(jié)果就是得到n * m行結(jié)果。

          posted @ 2008-08-22 22:33 丑男 閱讀(2509) | 評(píng)論 (0)編輯 收藏

          Fedora 7 安裝 nvidia顯卡驅(qū)動(dòng)

          第一步,到nvidia官方下載驅(qū)動(dòng),根據(jù)自己顯卡的型號(hào)選擇,一定要看readme
          第二步,驅(qū)動(dòng)只能在命令行方式下安裝,所以要修改/etc/inittab文件
              id:3:initdefault
                          3代表文本方式,5代表圖形方式
              修改后重啟系統(tǒng)
          第三步,執(zhí)行驅(qū)動(dòng),不出意外會(huì)非常的順利,之后shutdown -r now就完成了

          本人也是第一次安裝,有不對(duì)的地方請(qǐng)大家指正,祝好運(yùn)

          posted @ 2007-07-29 13:48 丑男 閱讀(789) | 評(píng)論 (0)編輯 收藏

          apache rewrite 簡(jiǎn)單應(yīng)用

          主要需求,DNSwww.mydomain.com指向www.mydomain.com/app/login.do

          目前是DNS指向某一個(gè)IP,不能將IP對(duì)應(yīng)到10.11.xxx.xxx/app/login.do

          生產(chǎn)環(huán)境WEB服務(wù)器是apache server


          解決辦法
          利用apache rewriter功能,在httpd.conf中找到

          #LoadModule rewrite_module modules/mod_rewrite.so

          將#號(hào)去掉,也就是把mod_rewrite.so模塊加載進(jìn)來(lái)

          之后在文件結(jié)尾處添加

          rewriteengine on
          rewriterule ^/$ http://10.11.xxx.xxx/app/login.do [R]

          posted @ 2007-07-16 21:47 丑男 閱讀(320) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)貼]jasperreport可以用Collection做為數(shù)據(jù)源



          jasperreport可以用Collection做為數(shù)據(jù)源,這種方式比用Connection方式更為靈活方便
           

          posted @ 2005-12-11 18:12 丑男 閱讀(425) | 評(píng)論 (0)編輯 收藏

          我的eclipse插件

          1.MyEclipse
             新出的GA4.0,功能非常強(qiáng)大,是我的首先。
             http://www.myeclipseide.com
          2.Log4E
             配合和Log4j日志功能
             http://log4e.jayefem.de/update
          3.i18n
             編輯國(guó)際化資源文件,省得寫(xiě)native2ascii了
             http://propedit.sourceforge.jp/eclipse_plugins/
          4.FreeMen
              隨時(shí)知道內(nèi)存使用情況
              http://www.junginger.biz/eclipse/

          posted @ 2005-09-04 16:13 丑男 閱讀(400) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)帖]學(xué)習(xí)Reflection

          Reflection 是 Java 程序開(kāi)發(fā)語(yǔ)言的特征之一,它允許運(yùn)行中的 Java 程序?qū)ψ陨磉M(jìn)行檢查,或者說(shuō)“自審”,并能直接操作程序的內(nèi)部屬性。例如,使用它能獲得 Java 類(lèi)中各成員的名稱(chēng)并顯示出來(lái)。
          Java 的這一能力在實(shí)際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計(jì)語(yǔ)言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒(méi)有辦法在程序中獲得函數(shù)定義相關(guān)的信息。
          JavaBean 是 reflection 的實(shí)際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過(guò) reflection 動(dòng)態(tài)的載入并取得 Java 組件(類(lèi)) 的屬性。
           
          1. 一個(gè)簡(jiǎn)單的例子
          考慮下面這個(gè)簡(jiǎn)單的例子,讓我們看看 reflection 是如何工作的。
          import java.lang.reflect.*;
          public class DumpMethods {
             public static void main(String args[]) {
                 try {
                     Class c = Class.forName(args[0]);
                     Method m[] = c.getDeclaredMethods();
                     for (int i = 0; i < m.length; i++)
                         System.out.println(m[i].toString());
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          按如下語(yǔ)句執(zhí)行:
          java DumpMethods java.util.Stack
          它的結(jié)果輸出為:
          public java.lang.Object java.util.Stack.push(java.lang.Object)
          public synchronized java.lang.Object java.util.Stack.pop()
          public synchronized java.lang.Object java.util.Stack.peek()
          public boolean java.util.Stack.empty()
          public synchronized int java.util.Stack.search(java.lang.Object)
          這樣就列出了java.util.Stack 類(lèi)的各方法名以及它們的限制符和返回類(lèi)型。
          這個(gè)程序使用 Class.forName 載入指定的類(lèi),然后調(diào)用 getDeclaredMethods 來(lái)獲取這個(gè)類(lèi)中定義了的方法列表。java.lang.reflect.Methods 是用來(lái)描述某個(gè)類(lèi)中單個(gè)方法的一個(gè)類(lèi)。
          2.開(kāi)始使用 Reflection
          用于 reflection 的類(lèi),如 Method,可以在 java.lang.relfect 包中找到。使用這些類(lèi)的時(shí)候必須要遵循三個(gè)步驟:第一步是獲得你想操作的類(lèi)的 java.lang.Class 對(duì)象。在運(yùn)行中的 Java 程序中,用 java.lang.Class 類(lèi)來(lái)描述類(lèi)和接口等。
          下面就是獲得一個(gè) Class 對(duì)象的方法之一:
          Class c = Class.forName("java.lang.String");
          這條語(yǔ)句得到一個(gè) String 類(lèi)的類(lèi)對(duì)象。還有另一種方法,如下面的語(yǔ)句:
          Class c = int.class;
          或者
          Class c = Integer.TYPE;
          它們可獲得基本類(lèi)型的類(lèi)信息。其中后一種方法中訪問(wèn)的是基本類(lèi)型的封裝類(lèi) (如 Integer) 中預(yù)先定義好的 TYPE 字段。
          第二步是調(diào)用諸如 getDeclaredMethods 的方法,以取得該類(lèi)中定義的所有方法的列表。
          一旦取得這個(gè)信息,就可以進(jìn)行第三步了——使用 reflection API 來(lái)操作這些信息,如下面這段代碼:
          Class c = Class.forName("java.lang.String");
          Method m[] = c.getDeclaredMethods();
          System.out.println(m[0].toString());
          它將以文本方式打印出 String 中定義的第一個(gè)方法的原型。
          在下面的例子中,這三個(gè)步驟將為使用 reflection 處理特殊應(yīng)用程序提供例證。
          模擬 instanceof 操作符
          得到類(lèi)信息之后,通常下一個(gè)步驟就是解決關(guān)于 Class 對(duì)象的一些基本的問(wèn)題。例如,Class.isInstance 方法可以用于模擬 instanceof 操作符:
          class A {
          }
          public class instance1 {
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("A");
                     boolean b1 = cls.isInstance(new Integer(37));
                     System.out.println(b1);
                     boolean b2 = cls.isInstance(new A());
                     System.out.println(b2);
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          在這個(gè)例子中創(chuàng)建了一個(gè) A 類(lèi)的 Class 對(duì)象,然后檢查一些對(duì)象是否是 A 的實(shí)例。Integer(37) 不是,但 new A() 是。
          3.找出類(lèi)的方法
          找出一個(gè)類(lèi)中定義了些什么方法,這是一個(gè)非常有價(jià)值也非常基礎(chǔ)的 reflection 用法。下面的代碼就實(shí)現(xiàn)了這一用法:
          import java.lang.reflect.*;
          public class method1 {
             private int f1(Object p, int x) throws NullPointerException {
                 if (p == null)
                     throw new NullPointerException();
                 return x;
             }
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("method1");
                     Method methlist[] = cls.getDeclaredMethods();
                     for (int i = 0; i < methlist.length; i++) {
                         Method m = methlist[i];
                         System.out.println("name = " + m.getName());
                         System.out.println("decl class = " + m.getDeclaringClass());
                         Class pvec[] = m.getParameterTypes();
                         for (int j = 0; j < pvec.length; j++)
                             System.out.println("param #" + j + " " + pvec[j]);
                         Class evec[] = m.getExceptionTypes();
                         for (int j = 0; j < evec.length; j++)
                             System.out.println("exc #" + j + " " + evec[j]);
                         System.out.println("return type = " + m.getReturnType());
                         System.out.println("-----");
                     }
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          這個(gè)程序首先取得 method1 類(lèi)的描述,然后調(diào)用 getDeclaredMethods 來(lái)獲取一系列的 Method 對(duì)象,它們分別描述了定義在類(lèi)中的每一個(gè)方法,包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 來(lái)代替 getDeclaredMethods,你還能獲得繼承來(lái)的各個(gè)方法的信息。
          取得了 Method 對(duì)象列表之后,要顯示這些方法的參數(shù)類(lèi)型、異常類(lèi)型和返回值類(lèi)型等就不難了。這些類(lèi)型是基本類(lèi)型還是類(lèi)類(lèi)型,都可以由描述類(lèi)的對(duì)象按順序給出。
          輸出的結(jié)果如下:
          name = f1
          decl class = class method1
          param #0 class java.lang.Object
          param #1 int
          exc #0 class java.lang.NullPointerException
          return type = int
          -----
          name = main
          decl class = class method1
          param #0 class [Ljava.lang.String;
          return type = void
          -----

          4.獲取構(gòu)造器信息
          獲取類(lèi)構(gòu)造器的用法與上述獲取方法的用法類(lèi)似,如:
          import java.lang.reflect.*;
          public class constructor1 {
             public constructor1() {
             }
             protected constructor1(int i, double d) {
             }
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("constructor1");
                     Constructor ctorlist[] = cls.getDeclaredConstructors();
                     for (int i = 0; i < ctorlist.length; i++) {
                         Constructor ct = ctorlist[i];
                         System.out.println("name = " + ct.getName());
                         System.out.println("decl class = " + ct.getDeclaringClass());
                         Class pvec[] = ct.getParameterTypes();
                         for (int j = 0; j < pvec.length; j++)
                             System.out.println("param #" + j + " " + pvec[j]);
                         Class evec[] = ct.getExceptionTypes();
                         for (int j = 0; j < evec.length; j++)
                             System.out.println("exc #" + j + " " + evec[j]);
                         System.out.println("-----");
                     }
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          這個(gè)例子中沒(méi)能獲得返回類(lèi)型的相關(guān)信息,那是因?yàn)闃?gòu)造器沒(méi)有返回類(lèi)型。
          這個(gè)程序運(yùn)行的結(jié)果是:
          name = constructor1
          decl class = class constructor1
          -----
          name = constructor1
          decl class = class constructor1
          param #0 int
          param #1 double
          -----
          5.獲取類(lèi)的字段(域)
          找出一個(gè)類(lèi)中定義了哪些數(shù)據(jù)字段也是可能的,下面的代碼就在干這個(gè)事情:

          import java.lang.reflect.*;
          public class field1 {
             private double d;
             public static final int i = 37;
             String s = "testing";
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("field1");
                     Field fieldlist[] = cls.getDeclaredFields();
                     for (int i = 0; i < fieldlist.length; i++) {
                         Field fld = fieldlist[i];
                         System.out.println("name = " + fld.getName());
                         System.out.println("decl class = " + fld.getDeclaringClass());
                         System.out.println("type = " + fld.getType());
                         int mod = fld.getModifiers();
                         System.out.println("modifiers = " + Modifier.toString(mod));
                         System.out.println("-----");
                     }
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          這個(gè)例子和前面那個(gè)例子非常相似。例中使用了一個(gè)新東西 Modifier,它也是一個(gè) reflection 類(lèi),用來(lái)描述字段成員的修飾語(yǔ),如“private int”。這些修飾語(yǔ)自身由整數(shù)描述,而且使用 Modifier.toString 來(lái)返回以“官方”順序排列的字符串描述 (如“static”在“final”之前)。這個(gè)程序的輸出是:
          name = d
          decl class = class field1
          type = double
          modifiers = private
          -----
          name = i
          decl class = class field1
          type = int
          modifiers = public static final
          -----
          name = s
          decl class = class field1
          type = class java.lang.String
          modifiers =
          -----
          和獲取方法的情況一下,獲取字段的時(shí)候也可以只取得在當(dāng)前類(lèi)中申明了的字段信息 (getDeclaredFields),或者也可以取得父類(lèi)中定義的字段 (getFields) 。

          6.根據(jù)方法的名稱(chēng)來(lái)執(zhí)行方法
          文本到這里,所舉的例子無(wú)一例外都與如何獲取類(lèi)的信息有關(guān)。我們也可以用 reflection 來(lái)做一些其它的事情,比如執(zhí)行一個(gè)指定了名稱(chēng)的方法。下面的示例演示了這一操作:
          import java.lang.reflect.*;
          public class method2 {
             public int add(int a, int b) {
                 return a + b;
             }
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("method2");
                     Class partypes[] = new Class[2];
                     partypes[0] = Integer.TYPE;
                     partypes[1] = Integer.TYPE;
                     Method meth = cls.getMethod("add", partypes);
                     method2 methobj = new method2();
                     Object arglist[] = new Object[2];
                     arglist[0] = new Integer(37);
                     arglist[1] = new Integer(47);
                     Object retobj = meth.invoke(methobj, arglist);
                     Integer retval = (Integer) retobj;
                     System.out.println(retval.intvalue());
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          假如一個(gè)程序在執(zhí)行的某處的時(shí)候才知道需要執(zhí)行某個(gè)方法,這個(gè)方法的名稱(chēng)是在程序的運(yùn)行過(guò)程中指定的 (例如,JavaBean 開(kāi)發(fā)環(huán)境中就會(huì)做這樣的事),那么上面的程序演示了如何做到。
          上例中,getMethod 用于查找一個(gè)具有兩個(gè)整型參數(shù)且名為 add 的方法。找到該方法并創(chuàng)建了相應(yīng)的 Method 對(duì)象之后,在正確的對(duì)象實(shí)例中執(zhí)行它。執(zhí)行該方法的時(shí)候,需要提供一個(gè)參數(shù)列表,這在上例中是分別包裝了整數(shù) 37 和 47 的兩個(gè) Integer 對(duì)象。執(zhí)行方法的返回的同樣是一個(gè) Integer 對(duì)象,它封裝了返回值 84。
          7.創(chuàng)建新的對(duì)象
          對(duì)于構(gòu)造器,則不能像執(zhí)行方法那樣進(jìn)行,因?yàn)閳?zhí)行一個(gè)構(gòu)造器就意味著創(chuàng)建了一個(gè)新的對(duì)象 (準(zhǔn)確的說(shuō),創(chuàng)建一個(gè)對(duì)象的過(guò)程包括分配內(nèi)存和構(gòu)造對(duì)象)。所以,與上例最相似的例子如下:
          import java.lang.reflect.*;
          public class constructor2 {
             public constructor2() {
             }
             public constructor2(int a, int b) {
                 System.out.println("a = " + a + " b = " + b);
             }
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("constructor2");
                     Class partypes[] = new Class[2];
                     partypes[0] = Integer.TYPE;
                     partypes[1] = Integer.TYPE;
                     Constructor ct = cls.getConstructor(partypes);
                     Object arglist[] = new Object[2];
                     arglist[0] = new Integer(37);
                     arglist[1] = new Integer(47);
                     Object retobj = ct.newInstance(arglist);
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          根據(jù)指定的參數(shù)類(lèi)型找到相應(yīng)的構(gòu)造函數(shù)并執(zhí)行它,以創(chuàng)建一個(gè)新的對(duì)象實(shí)例。使用這種方法可以在程序運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建對(duì)象,而不是在編譯的時(shí)候創(chuàng)建對(duì)象,這一點(diǎn)非常有價(jià)值。
          8.改變字段(域)的值
          reflection 的還有一個(gè)用處就是改變對(duì)象數(shù)據(jù)字段的值。reflection 可以從正在運(yùn)行的程序中根據(jù)名稱(chēng)找到對(duì)象的字段并改變它,下面的例子可以說(shuō)明這一點(diǎn):
          import java.lang.reflect.*;
          public class field2 {
             public double d;
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("field2");
                     Field fld = cls.getField("d");
                     field2 f2obj = new field2();
                     System.out.println("d = " + f2obj.d);
                     fld.setDouble(f2obj, 12.34);
                     System.out.println("d = " + f2obj.d);
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          這個(gè)例子中,字段 d 的值被變?yōu)榱?12.34。
          9.使用數(shù)組
          本文介紹的 reflection 的最后一種用法是創(chuàng)建的操作數(shù)組。數(shù)組在 Java 語(yǔ)言中是一種特殊的類(lèi)類(lèi)型,一個(gè)數(shù)組的引用可以賦給 Object 引用。觀察下面的例子看看數(shù)組是怎么工作的:
          import java.lang.reflect.*;
          public class array1 {
             public static void main(String args[]) {
                 try {
                     Class cls = Class.forName("java.lang.String");
                     Object arr = Array.newInstance(cls, 10);
                     Array.set(arr, 5, "this is a test");
                     String s = (String) Array.get(arr, 5);
                     System.out.println(s);
                 } catch (Throwable e) {
                     System.err.println(e);
                 }
             }
          }
          例中創(chuàng)建了 10 個(gè)單位長(zhǎng)度的 String 數(shù)組,為第 5 個(gè)位置的字符串賦了值,最后將這個(gè)字符串從數(shù)組中取得并打印了出來(lái)。
          下面這段代碼提供了一個(gè)更復(fù)雜的例子:
          import java.lang.reflect.*;
          public class array2 {
             public static void main(String args[]) {
                 int dims[] = new int[]{5, 10, 15};
                 Object arr = Array.newInstance(Integer.TYPE, dims);
                 Object arrobj = Array.get(arr, 3);
                 Class cls = arrobj.getClass().getComponentType();
                 System.out.println(cls);
                 arrobj = Array.get(arrobj, 5);
                 Array.setInt(arrobj, 10, 37);
                 int arrcast[][][] = (int[][][]) arr;
                 System.out.println(arrcast[3][5][10]);
             }
          }
          例中創(chuàng)建了一個(gè) 5 x 10 x 15 的整型數(shù)組,并為處于 [3][5][10] 的元素賦了值為 37。注意,多維數(shù)組實(shí)際上就是數(shù)組的數(shù)組,例如,第一個(gè) Array.get 之后,arrobj 是一個(gè) 10 x 15 的數(shù)組。進(jìn)而取得其中的一個(gè)元素,即長(zhǎng)度為 15 的數(shù)組,并使用 Array.setInt 為它的第 10 個(gè)元素賦值。
          注意創(chuàng)建數(shù)組時(shí)的類(lèi)型是動(dòng)態(tài)的,在編譯時(shí)并不知道其類(lèi)型。

          posted @ 2005-08-07 01:02 丑男 閱讀(428) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)帖]Eclipse快捷鍵

          作用域
          功能
          快捷鍵
          全局
          查找并替換
          Ctrl+F
          文本編輯器
          查找上一個(gè)
          Ctrl+Shift+K
          文本編輯器
          查找下一個(gè)
          Ctrl+K
          全局
          撤銷(xiāo)
          Ctrl+Z
          全局
          復(fù)制
          Ctrl+C
          全局
          恢復(fù)上一個(gè)選擇
          Alt+Shift+↓
          全局
          剪切
          Ctrl+X
          全局
          快速修正
          Ctrl1+1
          全局
          內(nèi)容輔助
          Alt+/
          全局
          全部選中
          Ctrl+A
          全局
          刪除
          Delete
          全局
          上下文信息
          Alt+?
          Alt+Shift+?
          Ctrl+Shift+Space
          Java編輯器
          顯示工具提示描述
          F2
          Java編輯器
          選擇封裝元素
          Alt+Shift+↑
          Java編輯器
          選擇上一個(gè)元素
          Alt+Shift+←
          Java編輯器
          選擇下一個(gè)元素
          Alt+Shift+→
          文本編輯器
          增量查找
          Ctrl+J
          文本編輯器
          增量逆向查找
          Ctrl+Shift+J
          全局
          粘貼
          Ctrl+V
          全局
          重做
          Ctrl+Y
           
          查看
          作用域
          功能
          快捷鍵
          全局
          放大
          Ctrl+=
          全局
          縮小
          Ctrl+-
           
          窗口
          作用域
          功能
          快捷鍵
          全局
          激活編輯器
          F12
          全局
          切換編輯器
          Ctrl+Shift+W
          全局
          上一個(gè)編輯器
          Ctrl+Shift+F6
          全局
          上一個(gè)視圖
          Ctrl+Shift+F7
          全局
          上一個(gè)透視圖
          Ctrl+Shift+F8
          全局
          下一個(gè)編輯器
          Ctrl+F6
          全局
          下一個(gè)視圖
          Ctrl+F7
          全局
          下一個(gè)透視圖
          Ctrl+F8
          文本編輯器
          顯示標(biāo)尺上下文菜單
          Ctrl+W
          全局
          顯示視圖菜單
          Ctrl+F10
          全局
          顯示系統(tǒng)菜單
          Alt+-
           
          導(dǎo)航
          作用域
          功能
          快捷鍵
          Java編輯器
          打開(kāi)結(jié)構(gòu)
          Ctrl+F3
          全局
          打開(kāi)類(lèi)型
          Ctrl+Shift+T
          全局
          打開(kāi)類(lèi)型層次結(jié)構(gòu)
          F4
          全局
          打開(kāi)聲明
          F3
          全局
          打開(kāi)外部javadoc
          Shift+F2
          全局
          打開(kāi)資源
          Ctrl+Shift+R
          全局
          后退歷史記錄
          Alt+←
          全局
          前進(jìn)歷史記錄
          Alt+→
          全局
          上一個(gè)
          Ctrl+,
          全局
          下一個(gè)
          Ctrl+.
          Java編輯器
          顯示大綱
          Ctrl+O
          全局
          在層次結(jié)構(gòu)中打開(kāi)類(lèi)型
          Ctrl+Shift+H
          全局
          轉(zhuǎn)至匹配的括號(hào)
          Ctrl+Shift+P
          全局
          轉(zhuǎn)至上一個(gè)編輯位置
          Ctrl+Q
          Java編輯器
          轉(zhuǎn)至上一個(gè)成員
          Ctrl+Shift+↑
          Java編輯器
          轉(zhuǎn)至下一個(gè)成員
          Ctrl+Shift+↓
          文本編輯器
          轉(zhuǎn)至行
          Ctrl+L
           
          搜索
          作用域
          功能
          快捷鍵
          全局
          出現(xiàn)在文件中
          Ctrl+Shift+U
          全局
          打開(kāi)搜索對(duì)話(huà)框
          Ctrl+H
          全局
          工作區(qū)中的聲明
          Ctrl+G
          全局
          工作區(qū)中的引用
          Ctrl+Shift+G
           
          文本編輯
          作用域
          功能
          快捷鍵
          文本編輯器
          改寫(xiě)切換
          Insert
          文本編輯器
          上滾行
          Ctrl+↑
          文本編輯器
          下滾行
          Ctrl+↓
           
          文件
          作用域
          功能
          快捷鍵
          全局
          保存
          Ctrl+X
          Ctrl+S
          全局
          打印
          Ctrl+P
          全局
          關(guān)閉
          Ctrl+F4
          全局
          全部保存
          Ctrl+Shift+S
          全局
          全部關(guān)閉
          Ctrl+Shift+F4
          全局
          屬性
          Alt+Enter
          全局
          新建
          Ctrl+N
           
          項(xiàng)目
          作用域
          功能
          快捷鍵
          全局
          全部構(gòu)建
          Ctrl+B
           
          源代碼
          作用域
          功能
          快捷鍵
          Java編輯器
          格式化
          Ctrl+Shift+F
          Java編輯器
          取消注釋
          Ctrl+
          Java編輯器
          注釋
          Ctrl+/
          Java編輯器
          添加導(dǎo)入
          Ctrl+Shift+M
          Java編輯器
          組織導(dǎo)入
          Ctrl+Shift+O
          Java編輯器
          使用try/catch塊來(lái)包圍
          未設(shè)置,太常用了,所以在這里列出,建議自己設(shè)置。
          也可以使用Ctrl+1自動(dòng)修正。
           
          運(yùn)行
          作用域
          功能
          快捷鍵
          全局
          單步返回
          F7
          全局
          單步跳過(guò)
          F6
          全局
          單步跳入
          F5
          全局
          單步跳入選擇
          Ctrl+F5
          全局
          調(diào)試上次啟動(dòng)
          F11
          全局
          繼續(xù)
          F8
          全局
          使用過(guò)濾器單步執(zhí)行
          Shift+F5
          全局
          添加/去除斷點(diǎn)
          Ctrl+Shift+B
          全局
          顯示
          Ctrl+D
          全局
          運(yùn)行上次啟動(dòng)
          Ctrl+F11
          全局
          運(yùn)行至行
          Ctrl+R
          全局
          執(zhí)行
          Ctrl+U
           
          重構(gòu)
          作用域
          功能
          快捷鍵
          全局
          撤銷(xiāo)重構(gòu)
          Alt+Shift+Z
          全局
          抽取方法
          Alt+Shift+M
          全局
          抽取局部變量
          Alt+Shift+L
          全局
          內(nèi)聯(lián)
          Alt+Shift+I
          全局
          移動(dòng)
          Alt+Shift+V
          全局
          重命名
          Alt+Shift+R
          全局
          重做
          Alt+Shift+Y

          posted @ 2005-08-06 00:02 丑男 閱讀(444) | 評(píng)論 (0)編輯 收藏

          簡(jiǎn)單應(yīng)用日期類(lèi)

          1.自定義格式
          ?? 用到j(luò)ava.text.SimpleDateFormat,其中參數(shù)如下:
          ???ss:秒
          ???mm:分
          ???hh:小時(shí)
          ???EEEE:星期
          ???MMMM:月份
          ?? dd:日期
          ?? yyyy:年份
          ????????Date?d?=?new?Date();
          ????????SimpleDateFormat?sdf?
          =?new?SimpleDateFormat("ss-mm-hh-EEEE-MMMM-dd-yyyy");
          ????????System.
          out.println(sdf.format(d));

          運(yùn)行結(jié)果
          58-21-11-星期五-七月-22-2005

          2.DateFormat自帶格式
          ??????? Date?date?=?new?Date();?

          ????????DateFormat?shortDateFormat?
          =?DateFormat.getDateTimeInstance(?DateFormat.SHORT,?
          ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? DateFormat.SHORT);?
          ???????????System.out.println(shortDateFormat.format(date));
          ?????????? //輸出結(jié)果????? 05-7-22 下午11:47


          ?????????? DateFormat mediumDateFormat = DateFormat.getDateTimeInstance(?DateFormat.MEDIUM,
          ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? DateFormat.MEDIUM);?
          ?????????? System.out.println?(mediumDateFormat.format(date));
          ?????????? //輸出結(jié)果?????? 2005-7-22 23:48:11


          ?????????? DateFormat longDateFormat =?DateFormat.getDateTimeInstance(?DateFormat.LONG,?
          ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? DateFormat.LONG);
          ?????????? System.out.println(longDateFormat.format(date));
          ?????????? //輸出結(jié)果????? 2005年7月22日 下午11時(shí)48分45秒


          ?????????? DateFormat fullDateFormat = DateFormat.getDateTimeInstance( DateFormat.FULL,
          ?????????????????????????????????????????????????????????????????????????????????????????????????????????????? DateFormat.FULL);
          ?????????? System.out.println?(fullDateFormat.format(date));
          ?????????? //輸出結(jié)果????? Saturday, September 29, 2001 8:44:45 PM EDT

          posted @ 2005-08-05 23:31 丑男 閱讀(435) | 評(píng)論 (0)編輯 收藏

          [轉(zhuǎn)帖]Log4j比較全面的配置

          LOG4J的配置之簡(jiǎn)單使它遍及于越來(lái)越多的應(yīng)用中了:Log4J配置文件實(shí)現(xiàn)了輸出到控制臺(tái)、文件、回滾文件、發(fā)送日志郵件、輸出到數(shù)據(jù)庫(kù)日志表、自定義標(biāo)簽等全套功能。擇其一二使用就夠用了,

           

          log4j.rootLogger=DEBUG,CONSOLE,A1,im
          log4j.addivity.org.apache=true

           

          # 應(yīng)用于控制臺(tái)

          log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
          log4j.appender.Threshold=DEBUG
          log4j.appender.CONSOLE.Target=System.out
          log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
          log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n


          #應(yīng)用于文件

          log4j.appender.FILE=org.apache.log4j.FileAppender
          log4j.appender.FILE.File=file.log
          log4j.appender.FILE.Append=false
          log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
          # Use this layout for LogFactor 5 analysis

           

          # 應(yīng)用于文件回滾

          log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
          log4j.appender.ROLLING_FILE.Threshold=ERROR
          log4j.appender.ROLLING_FILE.File=rolling.log
          log4j.appender.ROLLING_FILE.Append=true
          log4j.appender.ROLLING_FILE.MaxFileSize=10KB
          log4j.appender.ROLLING_FILE.MaxBackupIndex=1
          log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


          #應(yīng)用于socket
          log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
          log4j.appender.SOCKET.RemoteHost=localhost
          log4j.appender.SOCKET.Port=5001
          log4j.appender.SOCKET.LocationInfo=true
          # Set up for Log Facter 5
          log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
          log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n


          # Log Factor 5 Appender
          log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
          log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

           

          # 發(fā)送日志給郵件

          log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
          log4j.appender.MAIL.Threshold=FATAL
          log4j.appender.MAIL.BufferSize=10
          log4j.appender.MAIL.From=xxx@www.xxx.com
          log4j.appender.MAIL.SMTPHost=www.wusetu.com
          log4j.appender.MAIL.Subject=Log4J Message
          log4j.appender.MAIL.To=xxx@www.xxx.com
          log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
          log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

           

          # 用于數(shù)據(jù)庫(kù)
          log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
          log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
          log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
          log4j.appender.DATABASE.user=root
          log4j.appender.DATABASE.password=
          log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
          log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
          log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n


          log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.A1.File=SampleMessages.log4j
          log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
          log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout


          輸出到2000NT日志
           把Log4j壓縮包里的NTEventLogAppender.dll拷到WINNT\SYSTEM32目錄下

           log4j.logger.NTlog=FATAL, A8
           # APPENDER A8
           log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
           log4j.appender.A8.Source=JavaTest
           log4j.appender.A8.layout=org.apache.log4j.PatternLayout
           log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

          #自定義Appender

          log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender

          log4j.appender.im.host = mail.cybercorlin.net
          log4j.appender.im.username = username
          log4j.appender.im.password = password
          log4j.appender.im.recipient = xxx@xxx.net

          log4j.appender.im.layout=org.apache.log4j.PatternLayout
          log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

          posted @ 2005-07-24 22:25 丑男 閱讀(661) | 評(píng)論 (0)編輯 收藏

          學(xué)習(xí)Log4j筆記

          今天花了一天的時(shí)間來(lái)配置Log4j,沒(méi)想到要那么多時(shí)間,還問(wèn)了不少人,帖子也發(fā)了不少,不過(guò)最終還是搞定了,不過(guò)還有些問(wèn)題,請(qǐng)高手幫我看看,多謝了。

          1.首先是配置簡(jiǎn)單java project
          現(xiàn)在來(lái)看log4j.propertise
          #級(jí)別為DEBUG,二個(gè)輸出端,分別為stdout,R
          log4j.logger.helloappLogger=DEBUG, stdout, R

          #控制臺(tái)輸出
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n

          #保存到helloappLoggerlog.txt日志中,大小為100KB
          log4j.appender.R=org.apache.log4j.RollingFileAppender
          log4j.appender.R.File=F:/code/eclipse/workspace/TestLo4j/log/helloappLoggerlog.txt
          log4j.appender.R.MaxFileSize=100KB
          log4j.appender.R.MaxBackupIndex=1
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=%d{yyyy MMM dd HH:mm:ss} %-5p %c - %m%n

          java文件中用到日志
          package com;
          import org.apache.log4j.*;
          public class TestLog4j {
              static Logger logger = Logger.getLogger("helloappLogger");
              public static void main(String[] args) {
          //      PropertyConfigurator.configure("log4j.properties");
          //      如果.properties在當(dāng)前目錄下可以省略,我放在項(xiàng)目根目錄下,和com包同目錄
                  logger.debug("Debug ...");
                  logger.info("Info ...");
                  logger.warn("Warn ...");
                  logger.error("Error ...");
              }
          }

          2.web project中配置log4j

          還是先來(lái)看log4j.perproties

          #級(jí)別為DEBUG,三個(gè)輸出端,分別為stdout,FILE,R
          log4j.logger.hello=DEBUG, stdout, FILE, R

          #stdout是在控制臺(tái)輸出
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n

          #保存在rolling_log_file.log日志中,appender是RollingFileAppender
          #需要注意的是File=F:/code/...,不要寫(xiě)成\,這就一點(diǎn)害死我了
          log4j.appender.R=org.apache.log4j.RollingFileAppender
          log4j.appender.R.File=F:/code/eclipse/workspace/TestCvs/WebRoot/WEB-INF/rolling_log_file.log
          log4j.appender.R.MaxFileSize=100KB
          log4j.appender.R.MaxBackupIndex=1
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=%d{yyyy MMM dd HH:mm:ss} %-5p %c - %m%n

          #保存在log_file.log日志中,appender是FileAppender
          log4j.appender.FILE=org.apache.log4j.FileAppender
          log4j.appender.FILE.File=F:/code/eclipse/workspace/TestCvs/WebRoot/WEB-INF/log_file.log
          log4j.appender.FILE.Append=false
          log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
          log4j.appender.FILE.layout.ConversionPattern=%d{yyyy MMM dd HH:mm:ss} %-5p %c - %m%n

          之后要把它加入serlet中,和服務(wù)器一起啟動(dòng),方便其他程序使用

          public class Log4jServlet extends HttpServlet {
              public void init() throws ServletException {
                  ServletContext sct = getServletContext();
                  System.out.println("[Log4j]: The Root Path: " + sct.getRealPath("/"));
                  System.out.println("[Log4j]: InitServlet init start...");
                  PropertyConfigurator.configure(sct.getRealPath("/")
                        +getServletConfig().getInitParameter("propfile"));
                  System.out.println("[Log4j]: InitServlet init over.");
              }
          }

          <servlet>
              <description>init log4j of servlet</description>
              <display-name>log4j servlet</display-name>
              <servlet-name>Log4jServlet</servlet-name>
              <servlet-class>com.testCvs.Log4jServlet</servlet-class>
              <init-param>
               <param-name>propfile</param-name>
               <param-value>/WEB-INF/log4j.properties</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>

          注:log4j.properties放在/WEB-INF下,servlet自動(dòng)加載這個(gè)文件

          至此所有配置應(yīng)該成功了,不過(guò)還是有些問(wèn)題沒(méi)有解決好,問(wèn)了幾個(gè)朋友也沒(méi)有得到好的答復(fù),但是現(xiàn)在可以在控制臺(tái)和文件中輸出日志,基本功能達(dá)到了。還請(qǐng)各位有空給我看看這個(gè)錯(cuò)誤,歡迎指正。

          錯(cuò)誤如下:
          log4j:WARN No appenders could be found for logger (org.apache.jasper.compiler.JspRuntimeContext).
          log4j:WARN Please initialize the log4j system properly.

          posted @ 2005-07-24 22:10 丑男 閱讀(9670) | 評(píng)論 (8)編輯 收藏

          CVS配置學(xué)習(xí)筆記

          本文很簡(jiǎn)單,CVS的配置,做個(gè)學(xué)習(xí)筆記吧,省得忘了
          1.首先要下載cvsnt,是windows平臺(tái)下cvs服務(wù)器端軟件。http://www.cvsnt.com/cvspro/

          2.安裝軟件并查看服務(wù)是否啟動(dòng)

          3.建立Repositories,設(shè)置Server Settings,在Compatibility選中Respond as cvs 1.11.2 to version request,方便eclipse與其通信

          4.在eclipse中建立工程,之后右鍵project-->team-->share project-->,全部選擇默認(rèn)設(shè)置

          至此,cvs配置成功,還是花了些時(shí)間。請(qǐng)各位高手指正

          posted @ 2005-07-23 23:37 丑男 閱讀(648) | 評(píng)論 (0)編輯 收藏

          開(kāi)篇

          剛剛申請(qǐng)到blogjava,第一篇先報(bào)道吧!
          剛才大概看了幾個(gè)Blog,真是高手如林,其中就有大名鼎鼎的大胃,以前就教過(guò)我不少,看來(lái)又找到了學(xué)習(xí)的好地方。說(shuō)實(shí)話(huà),這段時(shí)間事情太多了,已經(jīng)有些日子沒(méi)寫(xiě)程序了,慚愧。不過(guò)從維護(hù)這個(gè)blog開(kāi)始,我要繼續(xù)學(xué)習(xí)了,爭(zhēng)取年底能找個(gè)好工作。

          posted @ 2005-07-20 16:16 丑男 閱讀(426) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 永川市| 吴忠市| 运城市| 托克逊县| 河东区| 霍城县| 哈尔滨市| 斗六市| 泰宁县| 会昌县| 宁陵县| 峨眉山市| 布拖县| 镇原县| 南汇区| 蓝山县| 广德县| 龙江县| 青冈县| 扬州市| 德惠市| 教育| 隆德县| 宁国市| 察雅县| 荣昌县| 积石山| 重庆市| 惠东县| 永靖县| 缙云县| 康定县| 原平市| 永定县| 越西县| 玉门市| 马边| 清苑县| 大石桥市| 金川县| 杂多县|