希格工作室

2012年12月26日 星期三

Func & Action


​這兩個用法我之前就很想搞懂,
但因為不知道怎麼去Google這關鍵字所以一直懸在心上
(<--實力差又沒在買書看的人)
剛好曹祖聖老師來公司上課時有舉到範例,解了我心懸一念
故在這邊簡略示意一般


一般我們可能會做個函式如:
​​​
01         public static string abc2(int a,int b)
02         {
03             return (a+b).ToString();
04         }


然後去針對abc2()去呼叫它(static別管它),一般的呼叫我們應該都知道了,只是我們也可以用Func的方式去呼叫它,如:
01 Func<int, int, string> dd = new Func<int, int, string>(abc2);


我們可以簡化它
01 Func<int, int, string> dd = abc2;


然後使用Invoke()或其它去執行它
01 dd.Invoke(1, 2)


但我們有時可能不希望函式寫一大堆,或是許多原因等,也可以用Func去改寫abc2:
01             Func<int, int, string> dd2 = new Func<int, int, string>(
02                 (a1,a2) =>
03                 {
04                     return (a1 + a2).ToString();
05                 }
06                 );


一樣用Invoke()或其它去執行它​
01 
02             Console.WriteLine(dd.Invoke(1, 2));
03             Console.WriteLine(dd.Invoke(1, 3));
04             Console.WriteLine(dd.Invoke(1, 4));
05             Console.WriteLine(dd.Invoke(1, 5));


有時依需求,因為這程式段落已經被拉到內層了使用了,所以甚至可以把a1 a2給省略或整合掉
01             int O1, O2;
02             O1 = 1; O2 = 2;
03             Func<string> dd2 = new Func<string>(
04                 () => {
05                     return (O1 + O2).ToString();
06                 }
07                 );
08             Console.WriteLine(dd2.Invoke());

​​​簡略來說就這樣囉,謝謝有來看的人觀賞~~~~
































嗯?怎麼沒講到Action?
其實Action一樣用法
只是Action對應的是void類型
而Func對應的是有return的類
看在你願意把畫面拉下來的份上,我還是貼個CODE好了
01             Action<int> fff = def;
02 
03             Action<int> dfqefqf = new Action<int>(
04                 delegate(int a1)
05                 {
06                 }
07                 );
08 
09 
10             Action<int> dfqefqf2 = new Action<int>(
11                 (no) =>
12                 {
13                     //code
14                 }
15                 );
以上~88

PS:有無發現,其實內圈的自定函式,是跑delegate的,只是剛才我都省略掉而已哦。

2012年11月20日 星期二

UserControl使用者控制項 CSS style


小筆記
使用UserControl(ascx)時,直接在.ascx裡寫css的style標籤
在IE(9)有可能不會動作?!
要把它拉出來變成css檔 放到主頁去載入才會動作...
不知為何,可能是我排版問題,暫記...

2012年10月19日 星期五

同步與非同步 - 口語化告訴你 Async

     今天是期中考,小明帶著滿心不悅的心情坐在坐位上等待著鐘響,當鐘響了,老師帶著考卷進來了,老師將考卷發給每一位學生,小明收到考卷後,開始了40分鐘的答案撰寫,而老師則在講臺旁坐著,等著同學答題,有的同學寫很快,20分鐘就交卷了,而小明卻寫了40分鐘才有辦法交卷,這段時間裡,由於老師必須要等同學都交卷了,才能收齊後回去教師室進行改考卷的動作,所以老師也只好等著小明一直到40分鐘後答完才能離開;考試結束了,小明很高興,招攬同學下課一起去網咖連線打電玩打了一整個下午,但是這段時間裡,老師並沒有閒著,因為老師正在教師室裡拼命的改同學的考卷,到了隔天上課,老師發回了考卷,但是此時小明卻高興不起來了。





    因為小明不及格,回家要被媽媽打~~~~~






    以上情境,如果我們把它翻譯成程式來撰寫,哪邊屬於同步?哪邊屬於非同步?
    

    之所以會想到這段故事,是因為和同事聊天時提到的,我們多多少少都寫過、看過相關程式或邏輯,但是如果你要解釋或說明時,要怎麼解釋給一個完全不懂的人聽呢?通常我們會貼了一大堆語法來說明,再不然就像網路上一堆說著專有名詞的文章,看完了其實只有"啊?"的感想,如果要你再說明給別人聽,同事說:仔細想想還真不知道怎麼講耶?


   好了,回到剛剛的問題,哪邊屬於同步與非同步呢?其實整串文仔細想想,很多地方都可以扯到,不過我只針對兩個大項來說:
  1. 小明寫了40分鐘考卷,而老師則坐在講臺旁等著。

  2. 小明和同學打網咖,而老師在改考卷。

這兩個情境中

(1)應該就屬於同步類的等待,因為對老師來講,我要進行下一步的資源,也就是改考卷所需要的考卷,還在小明那邊,我必需要等小明寫(處理)完,才有辦法進行。

(2)則應該屬於非同步的處理,因為對小明來講,小明想要知道的是我最後考完試之後的結果與分數,但是在等分數出來之前,小明不需要一直留在學校裡等老師改完,小明可以趁這段時間去做別的事(打網咖),等到明天,老師應該就改好考卷了,所以小明就花了一個下午去玩,之後就回家休息了,但是老師呢?可能得花一整個下午加上一整個晚上才能改完所有同學的考卷。

題外話,最後老師精神不濟,找了其他人幫他發考卷給同學,這個算...?


其它可參考的網站
What are actually synchronous/asynchronous operations

2012年9月21日 星期五

Tech Days 2012 手記(第三日)

DBI308 SQL Power Tools 擴充事件使用與效益提升實戰
DBI309 SQL Server 2012 on windows Core  新架構探討並與AlwaysOn完美整合
DBI311 Microsoft SQL Server2012稽核管理面面觀
DBI313 建置 升級與轉換您的資料庫-Data Tier Applications

  因為是一系列的,所以一起講
  重點在
1.透過擴充事件,可以針對單一事情進行監測,且可使用非同步方式回報,故理論上較不耗用SQL資源,而它有點類似物件的概念,故可進行組合、封裝等,未來Profiler trace...etc可能將被遺棄。(這裡有個疑問點是,如果未來Profiler真被遺棄,我沒有看到類似錄製並轉給Database Engine Tuning Advisor的demo,那 DETA要怎麼做? )
2.windows Core(Server Core)上裝SQL,但只支援2012版本
3.使用Server Core一場說可減少50%的SP,另一場說60%,誰對?
4.如果用GUI的Windows裝SQL,請把IE移掉,只裝SQL Engine,其它全部不裝,不關SQL的東西也都不要裝,當然最好呢,使用Server Core(意思是叫你換2012)
5.若是安裝必要條件需要FW3.5.1時,不要連WCF都選到,因為那等於裝了IIS
6.Audit log可設最大換用檔案與最大檔案數,避免過去一些問題。
7.Server Audit 全版本支援,Database則仍為Enterprise
8.請不要把SQL Server當PC使用,否則改用Server Core吧。

DEV308 精通JavaScript作Windows Store App 開發
  這堂課主要是在講MS可以讓你用JS寫WSApp,但是最好使用它所提供的腳本(WinJs MSApp.等),而由於它允許JS部份可進行較底層的操作,透過它提供的API,故有許多原生的指令在這還境下是不被允許使用,或是必須進行轉換才能使用的。
  如.open() .moveTo()...等 是被移除的
  close()變更行為
  .innerHTML禁止填入事件,非標準的標籤可能不被允許。
  這之中最令人意想不到的是...不能使用alert();,要改用Windows.UI.Popups.MessageDialog()
  禁止載入外部腳本,請先自行下載到專案內
  可Cross-Domain
  VS專案強制預設其為Strice Mode
  可使用iframe但其為web context 無法使用原App的功能,但其等級與Web相同,只是與App間的溝通將會有點困難,要用postMessage()
 以及眾多的地雷

2012年9月19日 星期三

Tech Days 2012 手記(第二日)

DBI304 新世代資料倉儲平行處理技術Microsoft SQL Server PDW
 資料倉儲功能比較
擴充性
  Fast Track 3.0PDW 1.0 AU3(Parallel Data warehousing)
資料量1~80T20~500TB
架構SMP 1SQL NodeMPP 8~10 SQL Node
高可用性可建置內建
擴充性Scale-UPScale-UP & Scale Out

AU3 Shell DB 自動Cost Based 最佳化



EXL202 Lync Server 2013
  可整合AD、sharepoint、其它通訊軟體
  支援voip
  可撥打一般電話
  主打多人視訊最高有HD畫質
(長的跟MSN非常像)



AAP301 研發主管的管理實踐 - 建立敏捷開發的團隊
  這大概是最認真的一堂吧,李老師是我去Techday最想聽的一位,主題是以SCRUM建立敏捷開發的團隊。
  在剛開始時,李老師問了一句:沒聽過SCRUM的舉手!
  我二話不說就舉了,實際上我也沒聽過,然後受贈了一本書[硝煙中的Scrum和XP],沒想到會拿到書,心中當然很高興,不過之後很可惜,到最後都沒拿到光碟。
  依解說、Scrum是一個流程的框架,不只用在程式專案,也能應用在各種方面,Scrum定義下有主要的三個組成Product Owner、Scrum Master、Team,一個或多個Team及其成員,最好需要自主性的自組織的完成專案開發,並能夠使用一切手段來保證進度和品質的能力,而Team本身最好能夠不被打擾,因此需要Scrum Master,Scrum Master必須保證團隊能高效而不受打擾的工作,並優化工作條件、過程,Scrum Master需要是一個肯負責的人,因此Product Owner的角色很重要,要找出適合做的人,李老師說:PO在選Scrum Master時,不要小看平常木訥的人,也許他就是你要的人,木訥的人並不會不適合做,說不定正好相反。
   其它的因為我是第一次知道這個,故只是把開頭的內容照唸而已,我也還不懂,故不多述,以下是一些課程上的一言(希望沒記錯):
  •   一個人需不需要使用Scrum ?不需要
  •   VS2012已套用Scrum 框架。
  •  Scrum Master要主持並清楚知道每日專案執行時遇到的任何困難,並盡快排除障礙。
  •  不要讓開發團隊受到非開發以外的任何干擾
  •  加強使用者回饋的機制,最好是能夠在Scrum Master要主持的週期性會議或討論當時之前,能夠得到回饋,Scrum Master能在當下進行主持排解,使User能在最短時間得到哪些項目能夠被完成。
  • 不要讓團隊加班,而是讓團隊能夠在必要時才自主的加班,更重要的是,常態加班絕對是錯誤的, Scrum Master 必須要帶頭不加班,並且趕人下班。


DBI306 SQL Server Always On: 高可用性、備援與應用實例
  Windows Server容錯轉移叢集 WSFC(Windows Server Failover Clustering)
  AlwaysOn
     SQL Server Failover Cluster Instances(SQLFCI)
  可用性群組
    Availablity Group(AG)
建議在Windows Server Core上運行,可以不用擔心並減少50%以上的修補程式的必要,降低重新啟動的次數。
  支援多重子網路移轉 Multi-Subnet Clustering
  SMB檔案共用可能
  搭配可用性群組
預存:sp_server_diagnostics

建置沒有[見證磁碟]的WSFC叢集


DBI307 SQL Server 2012 跨國企業資料庫管理與效能調教
  老闆常問你的十大問題
  10.你的SQL還活著?
      A:使用msdb.dbo.sysmanagement_shared registered_servers_internal
  9.SQL剛被重開,你知道嗎?
      A:(待補)
  8.SQL硬碟空間還夠嗎?
      A:啟動Ole Automation Procedures,預存sp_OAMethod,搭配SQL Agent
  7.一整天的狀況還好嗎?
      A:(待補)
  6.剛USER說連線太久
      A:使用connect server切換AB資料庫 來try time
  5.系統參數有沒有被動過?
      A:DDL Trigger + DB Mail
  4.你知道Table被動過嗎?
      A:DDL Trigger + Database Level (DDL_TABLE_EVENTS)
  3.你知道已經CPU HIGH嗎
      A:Performance Dashboard 2012
  2.連線數已經超過危險指標了?
      A:Dynamic Performanceview (sys.dm_os_performance_counters)
  1.網頁已經block3分鐘了!
      A:DP View
           sys.dm_os_waitng_tasks
           sys.dm_exec_sessions
           sys.dm_os_wait_stats

2012年9月18日 星期二

Tech Days 2012 手記(第一日--DBI301 SQL Server 2012新語法應用實務)

SQL Server 2012新語法應用實務
講師:胡百敬

        在提這場次之前,不得不先說,在當初報名時,因為上班太認真(?)結果忘了選課時間,等到同事問我時才想起來,結果已經沒課可選了(才隔一天!),結果只好亂選。

       然後是今天這第一場課,報應就來了,沒想到的事情是,這場是在一樓,但來排隊的人非常的多,多到連裡面都快塞不下,連講師都調侃的說:不只是資料會爆滿,看樣子這場也是爆滿。

    SQL2012增加 SEQUENCE的命令,以往會用identity、GUID、Table seed建立唯一或獨立序列,現在亦可透過此方式建立類似功能,它是透過在SysDB裡建立一dbo.Obect去暫存,而亦可以透過一般Select去使用,預設是使用bigint記錄,可設立範圍區間,若取值時超過範圍時會error,但可使用新語令CYCLE使其循環,但不可以放在Where子句裡(至於比較差別,得等講師資料)。

   新增一例外處理方式THROW,應該類似.NET上的THROW方式,使用在CATCH裡,特性是在執行階段下發生例外,一律放棄批次,以及可使前端不會取得到不對的ERROR NUMBER

  新增很多的window(),例如可做上下筆Rows的比較運算和彙總等函數,特別提到的是Last_Val()這個函數在partition order和order by使用不同column時,結果會不一樣。

  新的分頁取值的指令方式(Offset Fetch),不同於Row_Number(),用較直覺的方式去呈現,但並沒有比較快(講師說的)

 Select語句後可接with xxx set進行自訂結果檢示


==============================================
其它兩堂只記關鍵字

AZR301 利用雲端建置高效率 高延展性大型應用程式
Azure功能:
讓雲端去幫忙負擔DB(大資料NoSql應用)
VIP交換
專用快取
CDN快取節點
Traffic Manger

DEV303 NodeJS的開發及應用
透過NPM使用
EJS
STYLUS
mongoDB(特色是DB用類JS語法去操作Select等)
SOKET IO
 

Tech Days 2012 手記(第一日--大會主題演講)

大會主題演講

照慣例一樣是微軟台灣區總經理,一樣是在推雲端。

其它主要是在推Windows 8即將正式上市,及新功能的推銷,如可透過觸控方式在特定圖片上選取你定義的位置,作為登入密碼,而不是用一般的文字帳密。

各種搭配雲端儲存所呈現的個人化介面和體驗

win8以動態磚為桌面主題,並在以不進入App時即時顯示重要資訊(如果你不知道是啥, 打開 Window Media Center 長的很像那樣 ),然後也可以切換舊介面。

能夠更快速的開機

之後有一些Demo重點
-------------------
VS2012上,提出開發市集的環境

------------------
Windows Azure上能自由的轉移VM
------------------
SQL 2012能夠線上將正在運作的DB進行切換、轉移、備援來換到另一個DB,而不影響線上任何USER進行的行為和資料。


有些忘了


另外可以發現,去年還在活躍的小光,今年連個影都沒有,可憐的小光,就這樣被遺棄了。

2012年9月10日 星期一

多型不易必自斃

詞意:因為多型覺得不好理解而避而遠之,遲早會自爆。

善用多型真的可以改善很多東西
否則當整體需求一變,程式就有得改了
以上為自我督促

2012年4月11日 星期三

Linq時代的分頁使用關係 (C#)

       在早期,我們在完成一個網頁表單會使用DataGird這個物件來實現,而DataGird這個物件本身也就支援著分頁的功能了。不過,我們應該都知道DataGird實現分頁的方式就是將資料透過ViewState保留後,再從中篩選要顯示的資料給User來檢閱,也因此在大量資料下,除了會造成資料庫負擔外,更會因為ViewState過大的關係,使得網頁停止回應,導致整個掛掉。

      所以我們會利用資料篩選的方式,只透過回應少量且必要的資料來減低資料庫負擔並提高效能,而通常會透過一連串的SQL語法去達成,至今亦是如此。

      在SQL2000之前,我們可能會透過cursor的方式叫用sp_cursoropen及sp_cursorfetch來達成,而在SQL2005之後多了ROW_NUMBER()這個函數,讓我們方便替每筆資料列做編號,之後只要透過where語法去取用需要的編號範圍,即可達成分頁。

      例如我們有一語法取得資料表的幣別種類並替它編號
SELECT ROW_NUMBER() OVER (ORDER BY [Currency]) AS [ROW_NUMBER], [Currency], [CurrencyName] FROM [dbo].[Currency]
      結果大概長這樣


    如果我們打算將它分成兩頁並取第一頁前5筆時

select * from
( SELECT top 5 ROW_NUMBER() OVER (ORDER BY [Currency]) AS [ROW_NUMBER], [Currency], [ CurrencyName ] FROM [dbo].[Currency] )  AS   a
where [ROW_NUMBER] > 0
    結果自然長這樣
     而至於我為什麼要講那麼多SQL呢,是因為使用Linq有著更令人一目瞭然的寫法,如:
var data = (from i in db.Currency select i).Skip(0).Take(5).ToList();

    好了....解決了(註:Skip是略過幾筆,Take是取得幾筆),當你使用SQL Profiler時會發現,Linq會自動幫你轉成類似語法,來達到資料分頁,不過這其實不是啥了不起的事...,因為這已經好幾年前的舊聞了,我這裡會講這個,主要只是要表達使用Linq後,在背後的執行狀況。

    在VS2005還是VS2008時,DataGird被捨棄了,取而代之的是GridView,而GridView可以搭配著各種DataSource容器,只要指定好DataSourceID,並在畫面上拖拖拉拉後,再將AllowPaging打開,分頁輕輕鬆鬆便做好了!而且更重要的是,透過Profiler去追蹤,你會發現DataSource傳送的SQL語法就是剛才所使用的ROW_NUMBER,簡直棒透了不是?

    這當然也不是新聞。

   問題在於一點,GridView必需搭配DataSource容器才得以自動完成[資料分頁],但是在分散式專案的架構下,想單單靠著指定DataSourceID來完成表單似乎有點難度,故在這情況下只好又做回原來的GridView.DataSource&DataBind()來製作表單,但不知道是不是由於DataSourceID太好用的關係吧?又或著有些人認為GridView搭配Linq會聰明的自己作分頁..?之類的,你可能會看到如下程式碼:

public void Page_Load(object sender, EventArgs e)
  {
     GridView1.DataSource = getData();
     GridView1.DataBind();
  }
  public IEnumerable<TBX> getData()
  {
     var data = from i in DB.Table select i;
     return data;
  }
        然後在介面上設定AllowPaging=true


        這是一個不知道該說什麼好的一件事,似乎會以為這樣就會替你完成[資料分頁]?那當然是不可能的...,GirdView並沒有你想像的聰明,它只會將資料全數取回後送給GridView1,存放在GridView1的ViewState裡,緊接著在裡頭進行著分頁動作,就又回到N年前的DataGird問題裡(即使你用別人開發的控件亦同)。

        要記得一個大原則,只要透過DataSource&DataBind()就代表你放棄好用的工具,所以所有功能你都得自己寫!!

       是故,請好好利用Skip和Take進行分頁吧。

        另外在Google時發現一篇文章,文章裡問道,為何我用Skip&Take後,出來的語法和想像的不大一樣?

       其實這問題很簡單,因為你下的就是告訴它我要先Skip(跳過)再Take(取用),所以出來的資料截取方式當然是要先等資料讀過後,才知道要where和Top哪邊,如果要像此文章裡的想法下,只Top一定數再where範圍的話...。

       只要反過來先Take再Skip就好囉!分頁程式如下:

public List<TheTable> ddd(int PageSize, int PageCount)
{
     Conn db = new Conn();
     var data = from i in conn.TheTable  select i;
     var Take = (PageSize * PageCount);
     var Skip = ( (PageCount - 1) * PageSize);
     return data.Take(Take).Skip(Skip).ToList();
}
之後只要去取用就好囉

public void Button1_Click(object sender, EventArgs e)
{
 GridView1.DataSource = getAList(GridView1.PageSize, int.Parse(PageCount.Text));
 GridView1.DataBind();
}


不過這個方法沒有詳細Debug,防呆做好的話理論上應該不會有問題....吧?
(甚至你想先Take再Take說不定也行?)

2012/4/19:
關於Take Skip,查執行計劃,效率上似乎一樣。

2012年4月7日 星期六

網站效能的追源溯本(Linq)

Linq真好用(廢話)

Linq搭配LinqToxxx or Entity的結合根本好用到不行

用不著寫一堆連線方案,也不用擔心SQL Injection,也不用因為寫SQL語句時,造成的一堆"字"亂七八糟的難維護,甚至連SQL都不用學了。

真是好用的東西

事不宜遲,就來寫個輸入一筆訂單,若存在符合訂單則修改數量,不存在則新增一筆,超過一筆以上則保留數量最多的並刪除其它多餘資料的標準Linq語句吧。



            var dbLink = new db();
            var catchOrder = from o in dbLink.OrderList
                             where o.OrderID == "J001"
                             select o;
            if (catchOrder.Count() == 0)
            {
                var newOrder = new OrderList();
                newOrder.OrderID = "J001";
                newOrder.OrderName = "新訂單01";
                newOrder.Quantity = 10;
                dbLink.OrderList.InsertOnSubmit(newOrder);
            }
            if (catchOrder.Count() == 1)
            {
                foreach (var upd in catchOrder)
                {
                    upd.Quantity = 11;
                }
            }
            if (catchOrder.Count() >= 2)
            {
                var MaxQuantity = catchOrder.Max(m => m.Quantity);
                var delSomeThing = from d in catchOrder
                                   where d < MaxQuantity
                                   select d;
                foreach (var delIt in catchOrder)
                {
                    dbLink.OrderList.DeleteOnSubmit(delIt);
                }
            }
            dbLink.SubmitChanges();


我們姑且不論是什麼情況會有這麼詭異的需求...那不是重點。

基本上類似這樣子的寫法應該很常見,但這語法裡有什麼問題存在?相信應該很容易知道。

Linq因為它是一個你要它做時,它才會動的東西,所以即使你在最開頭寫好了select from....,它並不會做任何事,只是放在那裡,等你找它做事,當只有在count、max....xxx等語句出現或foreach它時,才會與資料做連繫,所以在這一個簡單判斷的語法裡,總共至少需要叫資料庫做至少5~7次以上的動作,會不會太浪費資源了一點?

catchOrder.Count()catchOrder.Max()catchOrder.XXX()太好用了,又容易看懂,如果你覺得這沒什麼,結果瘋狂使用它,去試著想用的人多一點時,會發生什麼事吧?一個人是7次,1000個人就是7千次,千萬不要因為好用而濫用。

     


            var dbLink = new db();
            var catchOrder = from o in dbLink.OrderList
                             where o.OrderID == "J001"
                             select o;
            var bakOrder = catchOrder.ToList();
            int useCount = bakOrder.Count();
            if (useCount == 0)
            {
                var newOrder = new OrderList();
                newOrder.OrderID = "J001";
                newOrder.OrderName = "???01";
                newOrder.Quantity = 10;
                dbLink.OrderList.InsertOnSubmit(newOrder);
            }
            if (useCount == 1)
            {
                foreach (var upd in catchOrder)
                {
                    upd.Quantity = 11;
                }
            }
            if (useCount >= 2)
            {
                var MaxQuantity = bakOrder.Max(m => m.Quantity);
                var delSomeThing = from d in catchOrder
                                   where d < MaxQuantity
                                   select d;
                foreach (var delIt in catchOrder)
                {
                    dbLink.OrderList.DeleteOnSubmit(delIt);
                }
            }
            dbLink.SubmitChanges();

這邊做簡單的調整(但不代表最好,因為更好的有很多,這邊只是減少對資料庫溝通而已)
利用ToList先行將資料取得到記憶體中,接著計取Count保留,若有需要時亦用來計取Max,如此一來對資料庫要求的次數則從最少5~7次降為最少2次,如此便減少與資料庫之間來往,理論上而言效能應是比較好的。(實際情況請依狀況而定)

在撰寫時,最好搭配SQL Profiler瞭解你的Linq到底幹了什麼事。

2012年4月5日 星期四

網站效能的追源溯本(資料庫)

當你的網站慢了的時後,你第一時間會想什麼?

1.伺服器出問題?(IIS掛了?mem爆了?網域解析又出錯了? )
2.這支程式誰寫的?(又是xxx,快把他抓來罵)
3.大概是人太多了
4.大概是資料太多了
5.....
諸如此類的想法

如果這時候好死不死給上頭的知道了,一聲怒下,你就得開始狂查原因,翻遍所有程式,看遍所有server的設定,或狂打電話給中華電信,結果仍百思不得其解,最後上網GOOGLE,找到了許許多多網站調校的方法和建議,這當中往往都是叫你改程式,不然就再安裝新軟體,結果成本就又冒出一堆來了,只好冒死晉見老闆說要改程式(買軟體),然後被老闆白眼一頓後才核準,最後當你如願以償之後,卻發現上頭的還是跟你說一聲"喂!XXX怎麼還是那麼慢?",你可能會哭死

在你花時間改程式,加設備,搬資料,調整javascript,JPG,...,各種延遲載入,修改各介面的Response方式....諸如此類耗時費神的動作前,花個5~20分鐘重新看一下最根本的東西吧

資料庫

基本上我要講的對很多人而言是廢話,但卻又是最容易讓人遺忘的基本,資料庫是讓人塞資料用的,要塞資料一定會佔空間啊,所以你當時在建資料庫時給它多少空間?快滿時的成長空間又是多少?想想你從系統剛上線時到現在的大小差了多少?由此你就會知道你的資料存在硬碟裡到底有多散了...,越散當然越慢啊。

再來你的log檔(ldf)和資料庫檔(mdf)是不是放在同一個實體硬碟?如果是,把管資料庫的抓來痛揍一頓吧。

有無使用檔案群組(file group)功能?如果沒有,趕快用吧;如果有...麻煩看一下用到哪去了?你確定真的有正確使用?

多久沒重建你的索引了?

多久沒"完整"備份你的資料庫了?

最基本的基本...你用什麼東西當你的索引?都是varchar?甚至前面多個n? or table時不時有一堆null?別以為有些人建議varchar和char執行速度沒啥差別,null和非null也可省好多空間...當你增刪修改個N次後,你就又會知道你的資料到底又有多散了...

SQL的服務沒用到的裝了一堆?如MSSQL的Reporting Service之類的有真正用到再裝吧。

還有偶偶錄一下Profiler餵給Database Engine Tuning Advisor看看有啥要改善的吧

等到這些最基本的確定沒問題了,再去思考那些複雜的問題吧,因為資料破碎這種事,就跟燒開水一樣,你不燒它,你就沒水喝,你不燒它,你就沒電用(因為從那個放風箏被電到的人發現電以來,我們發電的方式依舊是燒開水),你不去注意破碎,你永遠被罵。

噓:回資料太多的都是廢話...除非你的DB每個都不知道多少個G...而且又同在一個instance

分享複雜的問題的參考資料:
DB:
網站效能分析操作心法-第8回-從資料庫來調校
網站效能分析操作心法-第9回-從資料庫來調校
OTHER:
快速揪出網站效能不佳的罪魁禍首