1. 程式人生 > >如何處理PHP和MYSQL的併發以及優化

如何處理PHP和MYSQL的併發以及優化

sql優化,資料快取和頁面靜態化
首先各種優化程式邏輯優化資料庫優化硬體橫向擴充套件
資料hash、伺服器提升效能、表hash、出錢找oraclec出解決方案
頁面靜態化:
Php頁面靜態化有兩種,第一,php模板,比如:smarty。第二,url偽靜態,通過urlrewrite實現這種做法可以提高網站的排名和收索
像一些管理性質的網站,比如:新聞釋出系統、CMS等,使用php模板靜態化。一般的網站偽靜態就可以了
資料快取:
php程式常規的獲取資料的流程是:
1.使用者向php程式傳送請求
2.php請求從資料庫中取出資料
3.傳送給使用者
但是當網站的訪問量非常大的時候資料庫往往成為制約系統性能的瓶頸,為了減輕大規模請求對資料庫造成的壓力,簡單的方法可以採用資料快取來減輕資料庫的壓力,下面就簡單的介紹一下常規的資料快取方法:

具體的步驟:
1.使用者請求
2.判斷快取是否存在或者是否過期
3.如果快取不存在或者快取已經過期,從資料庫中讀出資料;如果沒有過期,讀取快取
4.傳送給使用者
檔案方式快取資料示例程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

//資料庫連線省略


$cache_dir='cache';//快取資料夾

$cache_time='60';//快取時間

$sql='select*fromtest';

$cache_file=$cache_dir.'/'.md5($sql);//以sql語句的md5值作為快取檔名(當然也可以用其他方式)


//如果快取存在並且快取未過期

if(file_exists($cache_file)&&time()-filemtime($cache_file)<$cache_time){


$data=unserialize(file_get_contents($cache_file));//讀取快取後反序列化

}else{

//讀取資料庫

$query=mysql_query($sql);

//省略...

$data="資料庫中讀取...";

//把讀取的資料序列化後寫入快取

file_put_contents($cache_file,serialize($data));

}

//呵呵,這裡就是想要的資料

print_r($data);

Memcache快取資料示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//先要安裝memcache服務端和memcachephp擴充套件

$memcache=newMemcache;


$memcache->connect('localhost',11211)ordie("Couldnotconnect");

$cache_time='60';//快取時間

$sql='select*fromtest';

$key=md5($sql);


if(!$memcache->get($key)){//如果快取不存在

//讀取資料庫

$query=mysql_query($sql);

//省略...

$data="資料庫中讀取...";

//把讀取的資料寫入快取

$memcache->set($key,$data,0,$cache_time);

}else{//快取存在

$data=$memcache->get($key);//讀取快取

}

print_r($data);

sql優化:
根據情況選擇最優的引擎是innodb還是myisam,比如mysql有很多第三方開源優化方案Facebook在mysql的第三方外掛使用上有很多做法。Pdo
innodb還是myisam
常用於讀取的資料表,sql引擎選擇myisam
常用於插入、修改、刪除等操作的資料表,sql引擎選擇innodb
1.查詢的模糊匹配
儘量避免在一個複雜查詢裡面使用LIKE'%parm1%'——紅色標識位置的百分號會導致相關列的索引無法使用,最好不要用.
解決辦法:
其實只需要對該指令碼略做改進,查詢速度便會提高近百倍。改進方法如下:
a、修改前臺程式——把查詢條件的供應商名稱一欄由原來的文字輸入改為下拉列表,使用者模糊輸入供應商名稱時,直接在前臺就幫忙定位到具體的供應商,這樣在呼叫後臺程式時,這列就可以直接用等於來關聯了。
b、直接修改後臺——根據輸入條件,先查出符合條件的供應商,並把相關記錄儲存在一個臨時表裡頭,然後再用臨時表去做複雜關聯
2.索引問題
在做效能跟蹤分析過程中,經常發現有不少後臺程式的效能問題是因為缺少合適索引造成的,有些表甚至一個索引都沒有。這種情況往往都是因為在設計表時,沒去定義索引,而開發初期,由於表記錄很少,索引建立與否,可能對效能沒啥影響,開發人員因此也未多加重視。然一旦程式釋出到生產環境,隨著時間的推移,表記錄越來越多
這時缺少索引,對效能的影響便會越來越大了。
這個問題需要資料庫設計人員和開發人員共同關注
法則:不要在建立的索引的資料列上進行下列操作:
*避免對索引欄位進行計算操作
*避免在索引欄位上使用not,<>,!=
*避免在索引列上使用ISNULL和ISNOTNULL
*避免在索引列上出現數據型別轉換
*避免在索引欄位上使用函式
*避免建立索引的列中使用空值。
3.複雜操作
部分UPDATE、SELECT語句寫得很複雜(經常巢狀多級子查詢)——可以考慮適當拆成幾步,先生成一些臨時資料表,再進行關聯操作
4.update
同一個表的修改在一個過程裡出現好幾十次,如:

updatetable1
           setcol1=...
           wherecol2=...;
           updatetable1
           setcol1=...
           wherecol2=...
           ......

象這類指令碼其實可以很簡單就整合在一個UPDATE語句來完成(前些時候在協助xxx專案做效能問題分析時就發現存在這種情況)
5.在可以使用UNIONALL的語句裡,使用了UNION
UNION因為會將各查詢子集的記錄做比較,故比起UNIONALL,通常速度都會慢上許多。一般來說,如果使用UNIONALL能滿足要求的話,務必使用UNIONALL。還有一種情況大家可能會忽略掉,就是雖然要求幾個子集的並集需要過濾掉重複記錄,但由於指令碼的特殊性,不可能存在重複記錄,這時便應該使用UNIONALL,如xx模組的某個查詢程式就曾經存在這種情況,見,由於語句的特殊性,在這個指令碼中幾個子集的記錄絕對不可能重複,故可以改用UNIONALL)
6.在WHERE語句中,儘量避免對索引欄位進行計算操作
這個常識相信絕大部分開發人員都應該知道,但仍有不少人這麼使用,我想其中一個最主要的原因可能是為了編寫寫簡單而損害了效能,那就不可取了
9月份在對XX系統做效能分析時發現,有大量的後臺程式存在類似用法,如:

......
           wheretrunc(create_date)=trunc(:date1)

雖然已對create_date欄位建了索引,但由於加了TRUNC,使得索引無法用上。此處正確的寫法應該是

wherecreate_date>=trunc(:date1)andcreate_date<PRE>

或者是

wherecreate_datebetweentrunc(:date1)andtrunc(:date1)+1-1/(24*60*60)

注意:因between的範圍是個閉區間(greaterthanorequaltolowvalueandlessthanorequaltohighvalue.),
故嚴格意義上應該再減去一個趨於0的小數,這裡暫且設定成減去1秒(1/(24*60*60)),如果不要求這麼精確的話,可以略掉這步。
7.對Where語句的法則
7.1避免在WHERE子句中使用in,notin,or或者having。
可以使用exist和notexist代替in和notin。
可以使用錶鏈接代替exist。Having可以用where代替,如果無法代替可以分兩步處理。
例子

SELECT*FROMORDERSWHERECUSTOMER_NAMENOTIN
           (SELECTCUSTOMER_NAMEFROMCUSTOMER)

優化

           SELECT*FROMORDERSWHERECUSTOMER_NAMEnotexist
           (SELECTCUSTOMER_NAMEFROMCUSTOMER)

7.2不要以字元格式宣告數字,要以數字格式宣告字元值。(日期同樣)否則會使索引無效,產生全表掃描。
例子使用:

SELECTemp.ename,emp.jobFROMempWHEREemp.empno=7369;
           不要使用:SELECTemp.ename,emp.jobFROMempWHEREemp.empno=&lsquo;7369&rsquo;

8.對Select語句的法則
在應用程式、包和過程中限制使用select*fromtable這種方式。看下面例子

使用SELECTempno,ename,categoryFROMempWHEREempno='7369&lsquo;
           而不要使用SELECT*FROMempWHEREempno='7369'

9.排序
避免使用耗費資源的操作,帶有DISTINCT,UNION,MINUS,INTERSECT,ORDERBY的SQL語句會啟動SQL引擎執行,耗費資源的排序(SORT)功能.DISTINCT需要一次排序操作,而其他的至少需要執行兩次排序
10.臨時表
慎重使用臨時表可以極大的提高系統性能
新浪微博對大資料量處理還用到了熱點資料處理方法類似於熱點資料快取
淘寶在大型活動時為了保證不宕機會採用降級服務
這些都是我知道的大併發處理方法