2013年3月8日星期五

Tune sql performance

1. table join 時, 先將各自 table 內的資料先過濾再 join 2. IN 與 EXISTS ■IN: 與 EXISTS 原理剛好相反 SELECT * FROM tableA a WHERE EXISTS ( SELECT 1 FROM tableB b WHERE a.col1 = b.col2 ) 相當於: FOR pointB IN ( SELECT * FROM tableB ) LOOP IF ( EXISTS ( SELECT 1 FROM tableA a WHERE a.col1 = pointB.col2 ) THEN /*OUTPUT THE RECORD*/ END IF; END LOOP; ■EXISTS: SELECT * FROM tableA a WHERE EXISTS ( SELECT 1 FROM tableB b WHERE a.col1 = b.col2 ) 相當於: FOR pointA IN ( SELECT * FROM tableA ) LOOP IF ( EXISTS ( SELECT 1 FROM tableB b WHERE pointA.col1 = b.col2 ) THEN /*OUTPUT THE RECORD*/ END IF; END LOOP; ■選擇時機: 外大內小 = IN,外小內大 = EXISTS, 同時應盡可能使用 NOT EXISTS 來代替 NOT IN,儘管二者都使用了NOT(都不能使用索引而降低速度),NOT EXISTS要比NOT IN查詢效率更高。 3. 在 where condition 中, 不要使用負向條件, 盡量用正向條件, 因為負向條件不行使用 Index 增加查詢效率 負向條件效率差: Ex: 1. WHERE column1 <> 1 AND column1 <> 2 2. WHERE column1 NOT IN (1, 2) 若一定要使用 NOT IN, 那麼使用 NOT EXISTS 取代 NOT IN 可增加查詢效率, 因為負向表列不行使用 Index 正向條件效率較好: Ex: 1. WHERE column1 < 1 AND column1 > 2 2. WHERE column1 IN (3, 4, 5…) 參考: http://www.dotblogs.com.tw/brian/archive/2013/03/06/95525.aspx http://eeluck.pixnet.net/blog/post/27559378-in%E5%92%8Cexists%E7%9A%84%E5%B7%AE%E7%95%B0 http://www.nowamagic.net/database/db_DifferenceBetweenInAndExist.php

2012年4月16日星期一

我自己的搜尋 Bar 搜尋我的網誌

2012年3月6日星期二

第一支app上架後學到的經驗

很多人都作了app,送上App StoreAndroid Market。每個人經過的血淚都不一樣,也常能在各種場合聽到各式分享。

筆者公司在先前也作了個簡單的倒數計時iPad app – DoodleTimer。送上了App Store,現在,在六十萬個app裡面還在努力中。其中也學到了許多的經驗。

Hacker News上看到這篇心得分享文,歸納了幾個原作者Ben Bloch發行第一支App – Whim,然後收掉的經驗心得。原文經驗整理的結構與邏輯不錯,順著原作的寫法,加上小部份自己看法,整理如下:

經驗一:挑產品名

這很基本,除了腦力激盪,集思廣益,找出如何符合產品意象,好念順口的產品名外,底下提供幾個也該注意的事項:

1. 檢查產品名是否被註冊商標

美國的商標可以在這裡查關鍵字,台灣的可以在智財局查詢,大陸的可以在中國商標網查詢。商標影響了商品最近最大的案例就是蘋果電腦的iPad商標在中國的官司了。

註冊商標是個有法律效應的東西,事前檢查絕對不會吃虧。

2. 先檢查這個名字能不能送App Store

這部分就是檢查是否已經有同名產品在App Store上面了,可上itune作關鍵字搜尋,看能不能查到什麼樣的產品。如果沒有同名產品,建議先想辦法佔住那個你要的名字,不然等到App做好的時候,或許會發現有人早你一天送上去,豈不氣死?

占住的方法,可能可以想辦法早點送上alpha版的app,即便審過了,不要發佈就不能被使用者下載。

3. 檢查網域名稱是否可用

基本上,App領域裡網域名稱不像做網站的那麼關鍵。不過,如果整體服務中有關鍵的網路部分功能,需要個網址,就必須早點檢查。

Ben建議,如果網名已經被拿走了,也別緊張,可以試試 後面加App,或是前面加Get。以DoodleTimer為例,就是申請 DoodleTimerApp.com 或是 GetDoodleTimer.com這樣的網址也是個好選擇。

4. 工具與技巧

選產品名是個有趣的過程。先把產品的感覺抓一抓,產品走向或族群也寫下幾個關鍵字,接下來就可透過這些字來想產品名稱。Ben建議了RhymeZone,可用來找相關字,這對英文非母語的我們來說應該是特別有用的一個取名網站工具。

經驗二:關於開張前後該注意的事

在公佈App之前,Ben已經給大約一百個朋友測試過他們ad-hocapp版本了。

不過,送上架之後才發現各式各樣的問題,而這些都不是透過Testflight + ad-hoc 測試app能解決的。 Apple審核通過,而且發行之後的版本,還是需要好好的測試一下。

不過,要測試這種版本就意味著他已經公開了。為了避免這個未經完整測試的版本被使用者下載了(抱怨),Ben提供了兩個作法:

  • 定高價,讓人不會去下載它。對於要加入測試的人,則給他promotion code
  • 限定只有特定地區的人可以下載app

如果是social類的app,一開始用封閉邀請的beta模式上架,也可以避免在產品沒達品質前,被太多人下載。

經驗三:分享 擴散的做法

Whim的致命問題之一就是專注於分享擴散這件事情。 讓用戶分享給他人,然後訊息或app就擴散出去了,這件事情說起來很容易,但做起來很困難。沒有動機的用戶會讓這整個擴散計劃崩潰。 Ben另外推薦了閱讀Plancast發佈在TechCrunch上的這個心得分享The Uphill Battle Of Social Event Sharing: A Post-Mortem for Plancast 。該文探討了分享擴散計劃中該注意的八大重點,若是採分享為擴散途徑的app開發者,可以讀一下。

經驗四:隨時要注意什麼是對的事情

Whim上線前,加了一個功能當你附近有朋友打開了Whim,你會收到通知。不過,附近的定義挺難的,在舊金山這樣擁擠的城市裡,兩英哩不太算附近,即便知道朋友開了這個app,也沒辦法去參與相關活動,因此這應該算是個惱人的功能。不過,Ben注意到,通知發出後,朋友的確會打開app,而這又觸發了其他的朋友打開這個app。雖然因為距離的關係,Whim沒辦法進一步地造成用戶間的互動,但是這個觀察到的行為變成現在Ben他們在專注的新專案了。

經驗五:要知道自己擅長什麼

大部份開始創業iOS app的人都是從工程角度出發,是擅長寫程式的人。跨技能的學習很重要,但考慮時程與資源限制,適時地將設計包出去給更有專長的人來處理肯定是個好主意。

經驗六:為何而戰?

創業者通常會犧牲睡眠,收入以及體力,因此你必須常問自己:為什麼要做?

是為了做的不一樣?改變世界?

還是這太有趣了,停不下來!

抑或是 這有一個賺錢的契機,不達目標絕不停止。

能全職做這樣的一件事情,是種幸福,也是很讓人興奮的一件事。

隨時問自己,你為什麼要做這個app??

結語

2010年的時候,Inside辦了Inside Out這個活動,當時在時間控制上,我們抓了iPad上的幾個應用程式下來用,運用他的大螢幕想提醒講者時間。

那時,筆者才赫然發現,這些app怎麼這麼不好用?沒辦法有效提醒在台上的講者所剩時間。 這也是筆者于現任公司練習的第一個App – DoodleTimeridea來源。

每個人都有他的第一次上架經驗,翻譯整理了Ben關於Whim App的經驗談,一樣是拋磚引玉,歡迎留言討論!

(轉載自:http://www.inside.com.tw/2012/03/03)




2012年2月24日星期五

使用Memcached提高.NET應用程式的性能

在應用程式運行的過程中總會有一些經常需要訪問並且變化不頻繁的資料,如果每次獲取這些資料都需要從資料庫或者外部檔案系統中去讀取,性能肯定會受到影響,所以通常的做法就是將這部分資料緩存起來,只要資料沒有發生變化每次獲取這些資料的時候直接從記憶體中區獲取性能肯定會大大地提高。在.NET中提供了一個Cache類可以實現這些功能。在ASP.NET中可以通過HttpContext 物件的 Cache 屬性或 Page 物件的 Cache 屬性來獲取這個類的實例。 在大部分情況下我們都可以使用Cache類來提高ASP.NET的性能,但是使用Cache類也有一些不足,比如我們不能指定Cache類所佔用的記憶體的大小,此外在Cache中緩存的資料沒有辦法被另一台機器上的應用程式直接訪問,因此在本文中提出另一種資料緩存方案,那就是使用分散式緩存。分散式緩存的特點是緩存的資料不必和應用程式在同一台機器上,從而大大增強了緩存資料的複用性。在本文介紹如何在.NET應用中使用Memcache作為分散式緩存。
Memcached介紹
Memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 為首開發的一款軟體。在通常的應用中我們都會將資料保存到資料庫中,每次需要的時候都會從資料庫去查詢這些資料,如果應用程式的使用者很多就會出現大量併發訪問資料庫的情況,這樣就會增加應用程式的回應時間,使用Memcached就可以有效解決這個問題。memcached是高性能的分散式記憶體緩存伺服器。一般的使用目的是,通過緩存資料庫查詢結果,減少資料庫訪問次數,以提高動態Web應用的速度、提高可擴展性。像大名鼎鼎的Facebook網站就使用了Memcached。稍後會提供Windows平臺上32位和64位元的Memcached程式。

為了提高性能,Memcached中的資料都保存在Memcached內置的存儲空間中。因為當Memcached重啟會導致其中的資料全部丟失,所以一般的方案是將資料保存在資料庫中,每次請求資料的時候先查看在Memcached有沒有緩存,如果有就直接從緩存中取出資料;如果沒有,就從資料庫中取出資料返回給應用程式並將請求的資料緩存到Memcached中,這樣一來下次請求相同的資料就可以直接從Memcached中讀取而不用再去查資料庫了;一旦對資料有更新,同時更新資料庫和Memcached

Memcached是一個命令列視窗程式,可以在命令列視窗中啟動也可以封裝在系統服務中啟動。在啟動Memcached時需要提供一些必須的參數,指定Memcached運行時監聽的埠和最大使用的記憶體大小等。如果緩存的資料大小超過指定記憶體,那麼Memcached就會按照LRU(Least Recently Used)演算法自動“刪除”不使用的緩存(標記為失效),新增的緩存資料就可以使用這些標記為失效的資料所佔用的記憶體,這樣就不用擔心Memcached超出所指定記憶體的問題。此外,為了提高性能,在緩存資料過期後Memcached並不是從實體記憶體中刪除緩存的資料,僅僅在取出改資料的時候檢查它是否已經過了有效期。

目前有多種平臺的Memcached版本,比如LinuxFreeBSDSolaris (memcached 1.2.5以上版本)Mac OS XWindows平臺,在Windows平臺上還有32位和64位版本。

Memcached有一套協定,利用這套協定可以對Memcached進行資料存取和查看Memcached的狀態,很多程式語言都依據這套協議來操作Memcached,比如PHPJavaCC++C#等。

獲取了對應平臺的Memcached版本就可以運行Memcached了。在這裡僅以Windows平臺上的32Memcached為例。

運行Memcached

memcached.exe -p 11121 -m 64

上面的命令是運行Memcached,指定它的監聽埠是11121(這是它的默認埠,可以指定為其它大於1024的埠,因為小於1024的埠已經有了預設指定),最大使用記憶體為64m,如果啟用了Windows防火牆,切記要在防火牆上打開這個埠。

在偵錯工具時可以使用下面的命令列來運行:
memcached.exe -p 11121 -m 64 -vv

這樣就會看到如下的結果:
slab class   1: chunk size     88 perslab 11915
slab class   2: chunk size    112 perslab  9362
slab class   3: chunk size    144 perslab  7281
slab class   4: chunk size    184 perslab  5698
slab class   5: chunk size    232 perslab  4519
slab class   6: chunk size    296 perslab  3542
slab class   7: chunk size    376 perslab  2788
slab class   8: chunk size    472 perslab  2221
slab class   9: chunk size    592 perslab  1771
slab class  10: chunk size    744 perslab  1409
slab class  11: chunk size    936 perslab  1120
slab class  12: chunk size   1176 perslab   891
slab class  13: chunk size   1472 perslab   712
slab class  14: chunk size   1840 perslab   569
slab class  15: chunk size   2304 perslab   455
slab class  16: chunk size   2880 perslab   364
slab class  17: chunk size   3600 perslab   291
slab class  18: chunk size   4504 perslab   232
slab class  19: chunk size   5632 perslab   186
slab class  20: chunk size   7040 perslab   148
slab class  21: chunk size   8800 perslab   119
slab class  22: chunk size  11000 perslab    95
slab class  23: chunk size  13752 perslab    76
slab class  24: chunk size  17192 perslab    60
slab class  25: chunk size  21496 perslab    48
slab class  26: chunk size  26872 perslab    39
slab class  27: chunk size  33592 perslab    31
slab class  28: chunk size  41992 perslab    24
slab class  29: chunk size  52496 perslab    19
slab class  30: chunk size  65624 perslab    15
slab class  31: chunk size  82032 perslab    12
slab class  32: chunk size 102544 perslab    10
slab class  33: chunk size 128184 perslab     8
slab class  34: chunk size 160232 perslab     6
slab class  35: chunk size 200296 perslab     5
slab class  36: chunk size 250376 perslab     4
slab class  37: chunk size 312976 perslab     3
slab class  38: chunk size 391224 perslab     2
slab class  39: chunk size 489032 perslab     2
<96 server listening
<112 server listening
<116 send buffer was 8192, now 268435456
<116 server listening (udp)

在用戶端還可以通過telnet來查看和操作Memcached,前提是伺服器端和用戶端都支援Telnet協定,在Windows7Windows2008中預設都不支援,需要在控制台中安裝和啟用。

首先打開控制台,然後點擊“打開或關閉Windows功能”,如下圖所示:
點擊“打開或關閉Windows功能”之後會看到當前系統啟用的功能的狀態,根據當前機器選擇打開Telnet伺服器端或者用戶端功能,如下圖所示:
經過上面的操作之後就可以在客服端遠端查看Memcached的狀態或者操作Memcached了。下面的命令就是連接到Memcached
telnet localhost 11121
連接之後會出現一個命令列視窗,在這個命令列視窗中輸入"stats"就可以看到當前Memcached的狀態,如下就是剛剛啟動的Memcached的狀態資料:
STAT pid 852
STAT uptime 1399
STAT time 1300979378
STAT version 1.2.5
STAT pointer_size 32
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 3
STAT total_connections 5
STAT connection_structures 4
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT evictions 0
STAT bytes_read 23
STAT bytes_written 415
STAT limit_maxbytes 67108864
STAT threads 1

END

通過這個資料我們就可以瞭解Memcached的狀態了。
這些資料所代表的意義如下:
pid32u,伺服器進程ID
uptime32u 伺服器執行時間,單位秒。
time 32u 伺服器當前的UNIX時間。
version string 伺服器的版本號。
curr_items 32u 伺服器當前存儲的內容數量 Current number of items stored by the server
total_items 32u 伺服器啟動以來存儲過的內容總數。
bytes 64u 伺服器當前存儲內容所佔用的位元組數。
curr_connections 32u 連接數量。
total_connections 32u 伺服器運行以來接受的連接總數。
connection_structures32u 伺服器分配的連接結構的數量。
cmd_get 32u 取回請求總數。
cmd_set 32u 存儲請求總數。
get_hits 32u 請求成功的總次數。
get_misses 32u 請求失敗的總次數。
bytes_read 64u 伺服器從網路讀取到的總位元組數。
bytes_written 64u 伺服器向網路發送的總位元組數。
limit_maxbytes 32u 伺服器在存儲時被允許使用的位元組總數。
上面的描述中32u64u表示32位和64位不帶正負號的整數,string表示是string類型資料。
 
.NET中應用Memcached
有很多.NET版本的Memcached用戶端程式,在這裡周公使用的Enyim Memcached,可以到https://github.com/enyim/EnyimMemcached/下載最新的版本。

要想在專案中使用Memcached,需要添加對Enyim.Caching.dll的應用。除此之外,我們可能還需要在config檔中配置Memcached的資訊(也可以在程式碼中指定,但那樣不靈活),如下就是一個config檔配置的例子:





 

 

   

     

      
 


     

   

   

     

       

         

         

       

       

     

   

 



如果我們配置了多個Memcached的實例,可以想上面的注釋部分那樣在節點下添加多個Memcached的實例配置。

這裡需要說明的是如果我們需要向Memcached中添加自訂資料類型時,我們需要將該資料類型添加上[Serializable]標記。

下面是一個Enyim Memcached的例子: 

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using Enyim.Caching;  
using Enyim.Caching.Memcached;  

/*  

  * 日期:2011-03-24  
 * 原文出處:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com  
 * 版權說明:本文可以在保留原文出處的情況下使用於非商業用途,對此不作任何擔保或承諾。  

 * */ 

namespace MemcachedMonitor  
{  

[Serializable]  

public class Person  

{  
    public int UserId { get; set; }  
    public string UserName { get; set; }  

}  
public class MemcachedDemo  
{  
    private static MemcachedClient client = new MemcachedClient("enyim.com/memcached");  


    public void SetDemo()  

    {  

        Person person = new Person { UserId = 1, UserName = "李剛" };  

        //不帶過期時間的存儲,Memcached將根據LRU來決定過期策略  

        bool success=client.Store(StoreMode.Add, person.UserName, person);  

        //帶過期時間的緩存  

        //bool success = client.Store(StoreMode.Add, person.UserName, person, DateTime.Now.AddMinutes(10));  

        Console.WriteLine("存儲[{0}]的結果:{1}", person.UserName, success);  
    }  

    public void GetDemo()  

    {  

        Person person = client.Get("李剛");  

        if (person != null)  

        {  

            Console.WriteLine("取回[{0}]的結果——UserId:{1},UserName:{2}", "李剛", person.UserId, person.UserName);  

        }  

        else 

        {  

            Console.WriteLine("取回[{0}]失敗!", "李剛");  

        }  

    }  


    public void MultiGetDemo()  

    {  

        List personNameList = new List();  

        for (int i = 0; i < 10; i++)  

        {  

            personNameList.Add("李剛00" + i);  

        }  

        //批量獲取,只通過一次網路通訊就取回所有personNameList中的指定的所有資料  

        IDictionary resultList = client.Get(personNameList);  

        Person person;  
        foreach (KeyValuePair item in resultList)  

        {  

            person = item.Value as Person;  

            if (person != null)  

            {  

                Console.WriteLine("取回[{0}]的結果——UserId:{1},UserName:{2}", "李剛", person.UserId, person.UserName);  

            }  

            else 

            {  

                Console.WriteLine("取回[{0}]失敗!", "李剛");  

            }  

        }  

    }  

}  

}  

說明:如果需要一次從Memcached中取回多個緩存的資料,可以參考MultiGetDemo()方法,這樣一來只需要一次網路通訊就可以取回全部資料,減少網路連線時間。此外,在Memcached用戶端可以使用Text或者Binary協定,經過周公千萬次測試比較,使用Binary協定性能略高於使用Text協定。在上面的config檔中周公就配置使用了Binary協定。

總結,使用Memcached這樣的分散式緩存可以大大提高應用程式的性能,經過周公測試,正確使用Memcached可以將單台伺服器的併發訪問數從20提高到1000左右,也就是提高了50倍,這是一個相當客觀的提升!限於篇幅,關於Memcached的更深更詳細的用法沒有在本篇介紹,此文算作抛磚引玉,讀者可以自行參考其它相關資料。


本文出自 http://zhoufoxcn.blog.51cto.com/792419/528212