軟件是對質量的不懈追求

          #

          用戶體驗: 網頁打開速度的心理學

          網頁打開的最佳速度

          2秒!

          許多研究都表明,用戶最滿意的打開網頁時間,是在2秒以下。用戶能夠忍受的最長等待時間的中位數,在6~8秒之間。這就是說,8秒是一個臨界值,如果你的網站打開速度在8秒以上,那么很可能,大部分訪問者最終都會離你而去。

          研究顯示,如果等待12秒以后,網頁還是沒有載入,那么99%以上的用戶會關閉這個網頁,不再等待。

          但是,如果在等待載入期間,網站能夠向用戶顯示反饋消息,比如一個進度條,那么用戶可以忍受的時間會延長到38秒。

          對訪問者的心理影響

          根據一些抽樣調查,訪問者傾向于認為,打開速度較快的網站質量更高,更可信,也更有趣。

          相對應地,網頁打開速度越慢,訪問者的心理挫折感就越強,就會對網站的可信性和質量產生懷疑。在這種情況下,用戶會覺得網站的后臺可能出現了一些錯 誤,因為在很長一段時間內,他沒有得到任何提示。而且,緩慢的打開速度會讓用戶忘了下一步要干什么,不得不重新回憶,這會進一步惡化用戶的使用體驗。

          這個指標對電子商務網站尤其重要。載入速度越快,就越容易使訪問者變成你的客戶,降低客戶選擇商品后、最后卻放棄結賬的比例。

          不過,網站反應速度也不宜太快,否則用戶會增加與服務器互動的頻率,這可能加大出現錯誤的概率。

          一些實證結果

          Google做過一個試驗,顯示10條搜索結果的頁面載入需要0.4秒,顯示30條搜索結果的頁面載入需要0.9秒,結果后者使得Google總的流量和收入減少了20%。

          Google地圖上線的時候,首頁大小有100KB,后來下降到70~80KB。結果,流量在第一個星期上升了10%,接下來的3個星期又再上升了25%。

          Amazon的統計也顯示了相近的結果,首頁打開時間每增加100毫秒,網站銷售量會減少1%。

          寬帶與窄帶的區別

          有研究顯示,寬帶用戶比窄帶用戶更沒有耐心。寬帶用戶愿意忍受的最長等待時間,往往只有4~6秒。

          網站制作者必須記住,在ADSL條件下,3~5秒就能載入的網頁,在窄帶條件下需要20~30秒才能打開。因此,網頁總的大小——包括圖片、Javascript和CSS文件的大小——不宜過大,這樣對寬帶和窄帶用戶都有利。

          posted @ 2009-11-01 18:42 BlakeSu 閱讀(221) | 評論 (0)編輯 收藏

          Oracle優化手段之提示

          1. /*+ALL_ROWS*/
          表明對語句塊選擇基於開銷的優化方法,並獲得最佳吞吐量,使資源消耗最小化.
          例如:
          SELECT /*+ALL_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

          2./*+FIRST_ROWS*/
          表明對語句塊選擇基於開銷的優化方法,並獲得最佳回應時間,使資源消耗最小化.
          例如:
          SELECT/*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

          3./*+CHOOSE*/
          表明如果資料字典中有訪問表的統計資訊,將基於開銷的優化方法,並獲得最佳的吞吐量;
          表明如果資料字典中沒有訪問表的統計資訊,將基於規則開銷的優化方法;
          例如:
          SELECT/*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

          4./*+RULE*/
          表明對語句塊選擇基於規則的優化方法.
          例如:
          SELECT/*+ RULE */ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';

          5./*+FULL(TABLE)*/
          表明對表選擇全局掃描的方法.
          例如:
          SELECT/*+FULL(A)*/ EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO='SCOTT';

          6./*+ROWID(TABLE)*/
          提示明確表明對指定表根據ROWID進行訪問.
          例如:
          SELECT/*+ROWID(BSEMPMS)*/ * FROM BSEMPMS WHERE ROWID>='AAAAAAAAAAAAAA' AND EMP_NO='SCOTT';
          7./*+CLUSTER(TABLE)*/
          提示明確表明對指定表選擇簇掃描的訪問方法,它只對簇物件有效.
          例如:
          SELECT/*+CLUSTER */ BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMS
          WHERE DPT_NO='TEC304' AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

          8./*+INDEX(TABLE INDEX_NAME)*/
          表明對表選擇索引的掃描方法.
          例如:
          SELECT/*+INDEX(BSEMPMS SEX_INDEX) USE SEX_INDEX BECAUSE THERE ARE FEWMALE BSEMPMS */ FROM BSEMPMS WHERE SEX='M';

          9./*+INDEX_ASC(TABLE INDEX_NAME)*/
          表明對表選擇索引昇冪的掃描方法.
          例如:
          SELECT/*+INDEX_ASC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';
          10./*+INDEX_COMBINE*/
          為指定表選擇點陣圖訪問路經,如果INDEX_COMBINE中沒有提供作為參數的索引,將選擇出點陣圖索引的布林組合方式.
          例如:
          SELECT/*+INDEX_COMBINE(BSEMPMS SAL_BMI HIREDATE_BMI)*/ * FROM BSEMPMS
          WHERE SAL<5000000 AND HIREDATE<SYSDATE;

          11./*+INDEX_JOIN(TABLE INDEX_NAME)*/
          提示明確命令優化器使用索引作為訪問路徑.
          例如:
          SELECT/*+INDEX_JOIN(BSEMPMS SAL_HMI HIREDATE_BMI)*/ SAL,HIREDATE
          FROM BSEMPMS WHERE SAL<60000;

          12./*+INDEX_DESC(TABLE INDEX_NAME)*/
          表明對表選擇索引降冪的掃描方法.
          例如:
          SELECT/*+INDEX_DESC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';

          13./*+INDEX_FFS(TABLE INDEX_NAME)*/
          對指定的表執行快速全索引掃描,而不是全表掃描的辦法.
          例如:
          SELECT/*+INDEX_FFS(BSEMPMS IN_EMPNAM)*/ * FROM BSEMPMS WHERE DPT_NO='TEC305';
          14./*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,...*/
          提示明確進行執行規劃的選擇,將幾個單列索引的掃描合起來.
          例如:
          SELECT/*+INDEX_FFS(BSEMPMS IN_DPTNO,IN_EMPNO,IN_SEX)*/ * FROM BSEMPMS WHERE EMP_NO='SCOTT' AND DPT_NO='TDC306';

          15./*+USE_CONCAT*/
          對查詢中的WHERE後面的OR條件進行轉換為UNION ALL的組合查詢.
          例如:
          SELECT/*+USE_CONCAT*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';

          16./*+NO_EXPAND*/
          對於WHERE後面的OR 或者IN-LIST的查詢語句,NO_EXPAND將阻止其基於優化器對其進行擴展.
          例如:
          SELECT/*+NO_EXPAND*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';

          17./*+NOWRITE*/
          禁止對查詢塊的查詢重寫操作.

          18./*+REWRITE*/
          可以將視圖作為參數.

          19./*+MERGE(TABLE)*/
          能夠對視圖的各個查詢進行相應的合併.
          例如:
          SELECT/*+MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO
          ,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO
          AND A.SAL>V.AVG_SAL;

          20./*+NO_MERGE(TABLE)*/
          對於有可合併的視圖不再合併.
          例如:
          SELECT/*+NO_MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;

          21./*+ORDERED*/
          根據表出現在FROM中的順序,ORDERED使ORACLE依此順序對其連接.
          例如:
          SELECT/*+ORDERED*/ A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;
          22./*+USE_NL(TABLE)*/
          將指定表與嵌套的連接的行源進行連接,並把指定表作為內部表.
          例如:
          SELECT/*+ORDERED USE_NL(BSEMPMS)*/ BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

          23./*+USE_MERGE(TABLE)*/
          將指定的表與其他行源通過合併排序連接方式連接起來.
          例如:
          SELECT/*+USE_MERGE(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

          24./*+USE_HASH(TABLE)*/
          將指定的表與其他行源通過哈希連接方式連接起來.
          例如:
          SELECT/*+USE_HASH(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;

          25./*+DRIVING_SITE(TABLE)*/
          強制與ORACLE所選擇的位置不同的表進行查詢執行.
          例如:
          SELECT/*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;

          26./*+LEADING(TABLE)*/
          將指定的表作為連接次序中的首表.

          27./*+CACHE(TABLE)*/
          當進行全表掃描時,CACHE提示能夠將表的檢索塊放置在緩衝區緩存中最近最少列表LRU的最近使用端
          例如:
          SELECT/*+FULL(BSEMPMS) CAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;

          28./*+NOCACHE(TABLE)*/
          當進行全表掃描時,CACHE提示能夠將表的檢索塊放置在緩衝區緩存中最近最少列表LRU的最近使用端
          例如:
          SELECT/*+FULL(BSEMPMS) NOCAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;

          29./*+APPEND*/
          直接插入到表的最後,可以提高速度.
          insert/*+append*/ into test1 select * from test4 ;

          30./*+NOAPPEND*/
          通過在插入語句生存期內停止並行模式來啟動常規插入.
          insert/*+noappend*/ into test1 select * from test4 ;

          posted @ 2009-10-30 15:22 BlakeSu 閱讀(129) | 評論 (0)編輯 收藏

          tortoiseCVS開機自動更新代碼

             作為開發人員,每天同步本地代碼是個好習慣,但好習慣不代表人人都愿意做,更不用說天天做。
          再細致的人也難免會偶爾忘掉,浪費不必要的時間,因此研究了如下腳本,開機即可啟動tortoiseCVS來同步代碼,
          總算省了自己不少事 :)

          TortoiseAct.exe CVSUpdate -l 需要更新的文件夾列表(空格分隔)

          將以上腳本置于update.bat文件中,并放到tortoise目錄下,然后設置開機運行update.bat即可。

          gook luck!

          posted @ 2009-08-27 16:58 BlakeSu 閱讀(215) | 評論 (0)編輯 收藏

          美國開源聯盟成立(轉)

          70多家大公司、學術機構和高資歷技術專家發起了一項旨在向美國政府機構灌輸開源技術優點的行動。Google、RedHat、Novell、Linux、Mozilla、Sun和電子前沿基金會在OSCON開源會議上宣布了這一消息,并攜手創立了美國開源聯盟。此次共同行動的目標是游說美國聯邦政府放棄私權代碼軟件,轉而考慮開源軟件。顧問委員會成員包括O’Reilly Media總裁蒂姆·奧萊利(Tim O’Reilly)和Linux基金會執行董事吉姆·澤姆林(Jim Zemlin)。

          美國開源聯盟的大衛·托馬斯(David Thomas)說:“軟件自由帶來的技術”可以使得政府的IT事務調度更加安全、節省成本、便捷,提供了更強的隱私以及消除供應商鎖定(vendor lock-in)的能力。”

          然而,游說絕非易事,因為在意見請求階段,小型開源公 司必須得設法達到和微軟一樣的地位。而且,政府官員過去曾表達過對開源方式的安全擔憂。有評論家認為,暴露在光天化日之下的源代碼可能會被黑客盯上,招致 風險。不過,也有觀點認為開放代碼可以在安全有保障的情況下進行。通過擯棄私權軟件模型,允許自由訪問系統源代碼,政府可不再依賴一小部分軟件承包商來構 建安全系統,取而代之的是一個完整的、用于布署防御黑客攻擊的編程社區。

          美國政府最重要的開源項 目之一是同國家安全局(NSA)的合作。國家安全局已經運用開源技術為使用SELinux系統的政府計算機處理多級安全問題。SELinux最初作為 Linux系統的修改版發布,此后在NSA同開源軟件商合作應對安全問題的工作中發揮了自己力量。Linux用戶最初曾懷疑NSA用此代碼庫來窺探他們的 電腦,但并沒有人在軟件中發現“后門”(back doors)。現在,成千上萬名政府雇員和Linux用戶都使用SELinux保護自己的機器。

          另一個成功的開源政府項目是Sunlight Lab的“美國應用”。該項目顯示政府開源對公共責任和集體合作解決方案都具有促進作用,在第一年便大獲成功。“美國應用”產生了一系列性能不凡的用戶生成項目,包括一個呼叫國會議員的火狐插件以及追蹤拖延式演說的網站。Sunlight Labs負責人克雷·約翰遜(Clay Johnson)和其他開源創新者在昨天的Google-O’Reilly開源大獎儀式上得到了如潮的贊美。

          蒂姆·奧萊利說:“發明不在于它開始時對世界造成了多大影響,而是最終造成了多少。”隨著新安全隱患的形成以及建立新數據集的重要性與日俱增,政府在提升為公民服務的過程中需要考慮開源的解決方案。

          如果你想為政府開源項目出一份力,請登陸“美國應用2”和美國開源聯盟

          posted @ 2009-08-05 13:49 BlakeSu 閱讀(207) | 評論 (0)編輯 收藏

          JAVA泛型類(轉)

          泛型是JDK 5.0后出現新概念,泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。這種參數類型可以用在類、接口和方法的創建中,分別稱為泛型類、泛型接口、泛型方法。

          泛型類引入的好處不僅在于減少代碼量,還在于一提供了編譯時期數據類型的檢查功能,可以提前預知錯誤的發生,增加代碼安全性,二是減少了強制類型轉換。下面定義一個泛型類

           Example GenericFX.java

           package org;

           public class GenericFX<E>

          {

               private E fx;

              

               public void setFX(E fx)

              {

                   this.fx = fx;

              }

           

               public E getFX()

               {

                   return fx;

               }

          }

          在此例中,GenericFX類就是要定義的泛型類,類型變量E是泛型類的類型參數,我們可以使用GenericFX<E>這樣的類型名來聲明一個泛型類。如

          GenericFX<E>  fx  = new GenericFX<E>(),其中E就是具體的類型, 下面看一個應用泛型類的例子.

           Example GenericFXDemo.java

           package org;

           public class GenericFXDemo

          {

               public void main(String[] args)

               {

                   GenericFX<Integer>  f1 = new GenericFX<Integer>(); 

                   GenericFX<Boolean>  f2 = new GenericFX<Boolean>();      

                  

                   f1.setFX(new Integer(10));

                   System.out.println(f1.getFX);//

                 

                   f2.setFX(new Boolean(true));

                   System.out.println(f2.getFX);//

               }

          }

          可以看到,f1,f2都是同一泛型類的對象引用,在取得不同參數類型對象時,已不需要實行類型轉換.

          如果像這樣修改一下代碼,

          f1.setFX(new Integer(10));

          Boolean  b = f1.getFX();

          System.out.println(b);   這里編譯就會報錯,告訴你這不安全.

          泛型類可以定義多個類型參數,像GenericFX<E,F>就要兩個類型參數。但是,無論有多少個類型參數,泛型仍然只需要一個類。如上GenericFX<Integer> GenericFX<Boolean>都屬于同一個泛型類GenericFX,f1,f2都只是該泛型類的一個應用,當然單一的GenericFX類是不能稱為泛型類的,必須要有<>和類型參數才可以,而像fx只是泛型類的成員變量。

          posted @ 2009-07-17 14:49 BlakeSu 閱讀(204) | 評論 (0)編輯 收藏

          xfce panel消失的問題

          昨天打開我心愛的xubuntu,發現上下的panel居然不見了,極其郁悶!雖然可以手工啟動,但出現了更惱人的問題,xfce啟動明顯慢了很多,控制臺可以看到錯誤信息“xfce4-panel is not running”.在xinitrc中,可以看到,如果panel啟動失敗,會重試很多次,這就是啟動變慢的元兇了。
          查了很多地方都沒有得到答案,最后還是在debian社區找到了線索,ubuntu他爸萬歲。。。

          Hm, after nuking ~/.cache/sessions/, the problem is gone.

          As I didn't make a copy beforehand I can longer reproduce the problem, so feel

          free to close the bug.


          說得很清楚了,只要刪除~/.cache/sessions/ 目錄下的所有內容就可以了。

          此問題我想與xfce的session保存有關。保存session時可能出現了文件損壞,導致這個問題。

          如果想一勞永逸,不保存session就好了,從個人經驗來講,保存session并沒有太多實用價值。

          posted @ 2009-06-23 09:39 BlakeSu 閱讀(481) | 評論 (0)編輯 收藏

          Oracle SQL優化(轉)

          原文地址:http://aofengblog.blog.163.com/blog/static/631702120083222117768/
          Oracle SQL的優化規則:
          • 盡量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替
                  用IN寫出來的SQL的優點是比較容易寫及清晰易懂,但是用IN的SQL性能總是比較低的,從ORACLE執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別:
                 ORACLE 試圖將其轉換成多個表的連接,如果轉換不成功則先執行IN里面的子查詢,再查詢外層的表記錄,如果轉換成功則直接采用多個表的連接方式查詢。由此可見用 IN的SQL至少多了一個轉換的過程。一般的SQL都可以轉換成功,但對于含有分組統計等方面的SQL就不能轉換了。

                  Oracle在執行IN子查詢時,首先執行子查詢,將查詢結果放入臨時表再執行主查詢。而EXIST則是首先檢查主查詢,然后運行子查詢直到找到第一個匹 配項。NOT EXISTS比NOT IN效率稍高。但具體在選擇IN或EXIST操作時,要根據主子表數據量大小來具體考慮。

                  推薦方案:在業務密集的SQL當中盡量不采用IN操作符。
          • 不用NOT IN操作符,可以用NOT EXISTS或者外連接+替代
                  此操作是強列推薦不使用的,因為它不能應用表的索引。

                  推薦方案:用NOT EXISTS 或(外連接+判斷為空)方案代替
          • 不用“<>”或者“!=”操作符。對不等于操作符的處理會造成全表掃描,可以用“<” or “>”代替
                  不等于操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。

                  推薦方案:用其它相同功能的操作運算代替,如:
                  1)a<>0 改為 a>0 or a<0
                  2)a<>’’ 改為 a>’’
          • Where子句中出現IS NULL或者IS NOT NULL時,Oracle會停止使用索引而執行全表掃描。可以考慮在設計表時,對索引列設置為NOT NULL。這樣就可以用其他操作來取代判斷NULL的操作
                  IS NULL 或IS NOT NULL操作(判斷字段是否為空)
                  判斷字段是否為空一般是不會應用索引的,因為B樹索引是不索引空值的。

                  推薦方案:
                  用其它相同功能的操作運算代替,如:
                  1)a is not null 改為 a>0 或a>’’等。
                  2)不允許字段為空,而用一個缺省值代替空值,如業擴申請中狀態字段不允許為空,缺省為申請。
                 3) 建立位圖索引(有分區的表不能建,位圖索引比較難控制,如字段值太多索引會使性能下降,多人更新操作會增加數據塊鎖的現象)
          •  當通配符“%”或者“_”作為查詢字符串的第一個字符時,索引不會被使用
          • 對于有連接的列“||”,最后一個連接列索引會無效。盡量避免連接,可以分開連接或者使用不作用在列上的函數替代。
          • 如果索引不是基于函數的,那么當在Where子句中對索引列使用函數時,索引不再起作用。
          • Where子句中避免在索引列上使用計算,否則將導致索引失效而進行全表掃描。
          • 對數據類型不同的列進行比較時,會使索引失效。
          • > 及 < 操作符(大于或小于操作符)
                 大于或小于操作符一般情況下是不用調整的,因為它有索引就會采用索引查找,但有的情況下可以對它進行優化,如一個表有100萬記錄,一個數值型字段A, 30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那么執行A>2與A>=3的效果就有很大的區別了,因為 A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。

                 推薦方案:用“>=”替代“>”。
          • UNION操作符
                 UNION在進行表鏈接后會篩選掉重復的記錄,所以在表鏈接后會對所產生的結果集進行排序運算,刪除重復的記錄再返回結果。實際大部分應用中是不會產生重復的記錄,最常見的是過程表與歷史表UNION。如:

              select * from gc_dfys
              union
              select * from ls_jg_dfys

              這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重復的記錄,最后返回結果集,如果表數據量大的話可能會導致用磁盤進行排序。

              推薦方案:采用UNION ALL操作符替代UNION,因為UNION ALL操作只是簡單的將兩個結果合并后就返回。

              select * from gc_dfys
              union all
              select * from ls_jg_dfys
          • LIKE操作符
                  LIKE 操作符可以應用通配符查詢,里面的通配符組合可能達到幾乎是任意的查詢,但是如果用得不好則會產生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用范圍索引。一個實際例子:用YW_YHJBQK表中營業編號后面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個范圍的查詢,性能肯定大大提高。
          • SQL書寫的影響(共享SQL語句可以提高操作效率)
              同一功能同一性能不同寫法SQL的影響

              如一個SQL在A程序員寫的為
              Select * from zl_yhjbqk

              B程序員寫的為
              Select * from dlyx.zl_yhjbqk(帶表所有者的前綴)

              C程序員寫的為
              Select * from DLYX.ZLYHJBQK(大寫表名)

              D程序員寫的為
              Select *  from DLYX.ZLYHJBQK(中間多了空格)

               以上四個SQL在ORACLE分析整理之后產生的結果及執行的時間是一樣的,但是從ORACLE共享內存SGA的原理,可以得出ORACLE對每個SQL 都會對其進行一次分析,并且占用共享內存,如果將SQL的字符串及格式寫得完全相同則ORACLE只會分析一次,共享內存也只會留下一次的分析結果,這不 僅可以減少分析SQL的時間,而且可以減少共享內存重復的信息,ORACLE也可以準確統計SQL的執行頻率。

              推薦方案:不同區域出現的相同的Sql語句,要保證查詢字符完全相同,以利用SGA共享池,防止相同的Sql語句被多次分析。
          • WHERE后面的條件順序影響
                 Oracle從下到上處理Where子句中多個查詢條件,所以表連接語句應寫在其他Where條件前,可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾。
                
                 WHERE子句后面的條件順序對大數據量表的查詢會產生直接的影響,如

              Select * from zl_yhjbqk where dy_dj = '1KV以下' and xh_bz=1

              Select * from zl_yhjbqk where xh_bz=1  and dy_dj = '1KV以下'

              以上兩個SQL中dy_dj(電壓等級)及xh_bz(銷戶標志)兩個字段都沒進行索引,所以執行的時候都是全表掃描,第一條SQL的dy_dj = '1KV以下'條件在記錄集內比率為99%,而xh_bz=1的比率只為0.5%,在進行第一條SQL的時候99%條記錄都進行dy_dj及xh_bz的 比較,而在進行第二條SQL的時候0.5%條記錄都進行dy_dj及xh_bz的比較,以此可以得出第二條SQL的CPU占用率明顯比第一條低。
          • 查詢表順序的影響
                 Oracle從右到左處理From子句中的表名,所以在From子句中包含多個表的情況下,將記錄最少的表放在最后。(只在采用RBO優化時有效)

                 在FROM后面的表中的列表順序會對SQL執行性能影響,在沒有索引及ORACLE沒有對表進行統計分析的情況下ORACLE會按表出現的順序進行鏈接, 由此因為表的順序不對會產生十分耗服務器資源的數據交叉。(注:如果對表進行了統計分析, ORACLE會自動先進小表的鏈接,再進行大表的鏈接)。
          • Order By語句中的非索引列會降低性能,可以通過添加索引的方式處理。嚴格控制在Order By語句中使用表達式
          • 當在Sql語句中連接多個表時,使用表的別名,并將之作為每列的前綴。這樣可以減少解析時間
          • 多利用內部函數提高Sql效率
          •  SQL語句索引的利用
            • 對操作符的優化(見前面)
            • 對條件字段的一些優化
              • 采用函數處理的字段不能利用索引
                    如:
                  substr(hbs_bh,1,4)=’5400’,優化處理:hbs_bh like ‘5400%’

                  trunc(sk_rq)=trunc(sysdate), 優化處理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)
              • 進行了顯式或隱式的運算的字段不能進行索引
                    如:

                  ss_df+20>50,優化處理:ss_df>30

                  ‘X’||hbs_bh>’X5400021452’,優化處理:hbs_bh>’5400021542’

                  sk_rq+5=sysdate,優化處理:sk_rq=sysdate-5

                  hbs_bh=5401002554,優化處理:hbs_bh=’ 5401002554’,注:此條件對hbs_bh 進行隱式的to_number轉換,因為hbs_bh字段是字符型。
              • 條件內包括了多個本表的字段運算時不能進行索引
                    ys_df>cx_df,無法進行優化

                    qc_bh||kh_bh=’5400250000’,優化處理:qc_bh=’5400’ and kh_bh=’250000’


              可能引起全表掃描的操作
          • 在索引列上使用NOT或者“<>”
          • 對索引列使用函數或者計算
          • NOT IN操作
          • 通配符位于查詢字符串的第一個字符
          • IS NULL或者IS NOT NULL
          • 多列索引,但它的第一個列并沒有被Where子句引用

                 ORACLE在SQL執行分析方面已經比較成熟,如果分析執行的路徑不對首先應在數據庫結構(主要是索引)、服務器當前性能(共享內存、磁盤文件碎片)、數據庫對象(表、索引)統計信息是否正確這幾方面分析。

          posted @ 2009-06-17 10:31 BlakeSu 閱讀(221) | 評論 (0)編輯 收藏

          struts2輸入驗證--補充(轉)

          原文地址:http://blog.csdn.net/ForWayfarer/archive/2008/09/20/2955812.aspx

          1.struts2怎么實現方法簽名(類似于struts1的DispatchAction):在strust.xml中配置如下
          <action ... method="register" ></action>
          <action ... method="login" ></action>
          <action ... method="insert" ></action>

          (1)struts2怎么實現分發驗證:對應于每個方法簽名,可以有相應的validate()方法如下
          public void validateRegister()
          public void validateLogin()
          public void validateInsert()

          (2)struts2怎么實現分發驗證:對應于每個方法簽名,可以有相應的驗證框架如下
          UserAction-register-validation.xml
          UserAction-login-validation.xml
          UserAction-insert-validation.xml

          2.驗證順序

          在struts1中,如果在FormBean中覆蓋了validate()方法,讓其放回null值,則驗證框架(xml驗證)就會失效。返回 null則代表驗證通過or無需驗證;覆蓋的validate()方法如果返回super.validate(mapping,request)即調用父 類的validate(mapping,request),驗證框架才會起作用。也就是說,如果想讓驗證框架有效,則不要覆蓋validate()方法, 如果除了驗證框架驗證,你還想在validate()方法中添加一些其他驗證,可以覆蓋validate()方法,但返回值須為 super.validate(mapping,request)。

          在struts2中類似。struts2的執行順序為:

          (1). 首先Struts2對客戶端傳來的數據進行類型轉換;

          (2). 類型轉換完畢后再進行輸入校驗,順序:UserAction-validation.xml --> UserAction-login-validation.xml --> public void validateLogin(){} --> public void validate(){};

          (3). 如果類型轉換和輸入校驗都沒有錯誤發生,那么進入login()方法/execuet()方法(調用商業邏輯).

          注意:如果類型轉換不成功,也同樣要進行輸入校驗,所以錯誤信息打印會將二者的錯誤信息全部打印出來

          3.struts2的錯誤信息

          struts2有兩種錯誤級別:addFieldError和addActionError

          addActionError(String anErrorMessage) -- Add an Action-level error message to this Action:看源代碼對于Action級別的錯誤信息,實際上是放置在ArrayList中的,action級別的error不會在表單中顯示。

          addFieldError(String fieldName, String errorMessage) --  Add an error message for a given field:看源代碼真正存放field級別錯誤信息的對象是LinkedHashMap,該LinkedHashMap的key是String類型 的,value是ArrayList類型的(addFielderror(String, ArrayList)),實際上是:LinkedHashMap<String, ArrayList<String>> errors。field級別的error會在表單中顯示。

          源代碼中還有這樣一個方法:public boolean hasErrors() { if (hasActionErrors() || hasFieldErrors()) ...} 則返回input頁面,表示不論是field級別的還是action級別的,只要錯誤容器不為空,就返回 到input頁面。

          另外:struts2驗證框架(xml驗證)是將錯誤保存在fielderror中的,而不是actionerror。所以在jsp顯示錯誤時要注意。

          4.struts2支持客戶端驗證,s標簽依然支持js事件,所以客戶端驗證推薦自己寫js,不過基本不用struts做客戶端驗證。此外,s標簽即使你不給其設置id屬性,s標簽也會自動生成一個id(通過查看頁面源代碼(獲得s標簽的html代碼)可獲得),如果你自定義了id,則會將s標簽自動生成的id覆蓋。


          posted @ 2009-06-17 09:40 BlakeSu 閱讀(1175) | 評論 (3)編輯 收藏

          多使用jdk中的類有益性能

          有以下兩點理由可以支持這一點:
          1.jdk中的類通常寫得比較考究
           
             怎么說jdk的實現者都是些相當有才華的人,隨便哪個來中國都是頂尖級的。我們自己重新實現jdk中的方法無疑是不明智的。
             而且搞了半天去實現個人家已經實現的東西也沒啥意思,恐怕要冒重新發明輪子之天下大不韙。真是得不償失。所以同志們,熱情的擁抱jdk吧!

          2.java的classloader機制

             java的classloader就是傳說中的雙親委派模式,無論當前classloader下有沒有要載入的類,都要先到最頂層classloader,然后再從上向下。最頂層就是對應jdk的,如果這層找到類,就直接返回,下層classloader就不需要再找了,這就是節省了搜索類的時間。


          以上純屬個人見解 ,歡迎不同觀點。

          posted @ 2009-05-31 22:35 BlakeSu 閱讀(109) | 評論 (0)編輯 收藏

          java中如何將OutputStream轉換為InputStream(翻譯)

          原文地址:http://ostermiller.org/convert_java_outputstream_inputstream.html

           如果你曾經使用java IO編程,你會很快碰到這種情況,某個類在OutputStream上創建數據而你需要將它發送給某個需要從輸入流讀取數據的類。
          你很快會被問道,“java中如何將OutputStream轉換為InputStream?”

           方法一:使用字節數組緩存數據
            最簡單的方法是用字節數組緩存數據。代碼如下:
               ByteArrayOutputStream out = new ByteArrayOutputStream();
               class1.putDataOnOutputStream(out);
               class2.processDataFromInputStream(
                  new ByteArrayInputStream(out.toByteArray())
               );
            于是,OutputStream就被轉換為InputStream了。

          方法二:使用管道
            第一種方法的問題是你必須有足夠的內存緩存所有數據。你可以使用文件系統緩存更多數據,但無論如何可處理數據的大小還是受到限制。
          解決方法是創建一個線程產生數據到PipedOutputStream。當前線程可從中讀取數據。
            PipedInputStream in = new PipedInputStream();
            PipedOUtputStream out = new PipedOutputStream(in);
            new Thread(
              new Runnable(){
                public void run(){
                  class1.putDataOnOutputStream(out);
                }
              }
            ).start();
            class2.processDataFromInputStream(in);

          方法三:使用循環緩存區
            方法二中的兩個管道流,實際上管理著一個隱藏的循環緩存區。使用一個顯式的循環緩存區更易于理解。CircularBuffers 有如下優點:
               一個CircularBuffers類而不是兩個管道類。
              較于緩存所有數據和額外線程的方法更容易使用。
              你可以更改緩存大小而不必受限于管道緩存區1K的固定緩存大小。
           
            多線程情形:
               CircularByteBuffer cbb = new CircularByteBuffer();
            new Thread(
              new Runnable(){
                public void run(){
                  class1.putDataOnOutputStream(cbb.getOutputStream());
                }
              }
            ).start();
            class2.processDataFromInputStream(cbb.getInputStream());
            單線程情形:
            // buffer all data in a circular buffer of infinite size
            CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
            class1.putDataOnOutputStream(cbb.getOutputStream());
            class2.processDataFromInputStream(cbb.getInputStream());


          posted @ 2009-05-17 21:40 BlakeSu 閱讀(1099) | 評論 (0)編輯 收藏

          僅列出標題
          共12頁: First 上一頁 4 5 6 7 8 9 10 11 12 下一頁 
          主站蜘蛛池模板: 大安市| 石门县| 娱乐| 兴业县| 贡山| 瑞丽市| 赤壁市| 恩施市| 陇南市| 松阳县| 青神县| 汾阳市| 赤壁市| 崇左市| 黄陵县| 宜兰县| 司法| 铜陵市| 克山县| 汤原县| 榆树市| 张家川| 赤水市| 龙山县| 淮北市| 天气| 云南省| 泸水县| 浦县| 林口县| 云安县| 四子王旗| 两当县| 富裕县| 舞钢市| 盈江县| 临漳县| 梁山县| 南城县| 隆昌县| 柞水县|