2015-04-26 41 views
0

我遇到的問題,像這樣無數次,一直有一種感覺,這不是最有效的邏輯和我似乎無法找到一個直接的答案:PHP分支優化和效率

在事件需要根據某些標準檢查數據庫,如果匹配成立,則更新記錄,如果匹配爲假,則轉到另一個語句,如果所有數據庫匹配都返回false,最後插入新記錄,是一種更有效的方法來優化當前的分支?

$id = *first query to look for id* //returns null if no match 
if (is_null($_id)) { #no match 
    $id = *fallback query looking for id *; -->returns null if no match 
} 
if (is_null($id)) {#still no match 
    $id = *last fallback query looking for id*; -->returns null if no match 
} 


if (is_null($id)) { # no match was found, doesn't exist in DB so insert it 
    //code to INSERT the new record 
} else { #match was found 
    //code to update the record* 
} 
+0

我想我們需要查看您的實際查詢以提供一個很好的答案。 – Mooseknuckles

回答

1

最有效的將是運行一個單一MySQL的聲明...

INSERT ... ON DUPLICATE KEY UPDATE 

這種做法可能不符合你的使用情況,但消除了檢查行存在的疑問提高性能。只要嘗試插入該行,如果MySQL違反唯一鍵約束,MySQL將拒絕它,不需要使用單獨的SELECT語句進行檢查。如果插入行的嘗試引發「重複鍵」異常,則將執行UPDATE部分中指定的分配。

此方法確實要求表至少有一個唯一約束,超出了AUTO_INCREMENT或系統分配的代理鍵。再次,您的用例可能不符合此要求,因此此方法可能不適用。


另一個說明:使用問題中概述的方法,併發系統中存在競爭條件的可能性。客戶端運行SELECT來查找行,並在未找到時運行後續的INSERT。第二個會話也可以查找同一行,但找不到它,並嘗試插入它。

問題是數據庫操作「檢查一行並插入,如果它不存在」不是原子的,因爲有多個往返行程。

db session 1 - check if row exists, not found 
db session 2 - check if row exists, not found 
db session 1 - insert the row - succeed 
db session 2 - insert the row - FAIL - because row already inserted 

如果我們被卡住運行單獨SELECT的方法來找出一個「匹配」的行存在,那麼我們至少可以試圖避免多次往返定位行,通過合併在單個語句中查找匹配行的查詢;我們應該至少可以得到兩個單獨的SELECT語句和一個UNION ALL,我們可以返回一個鑑別器列來區分哪個查詢返回了一行。