2009-07-30 26 views
1

如果您的應用程序代碼中有一組記錄ID,那麼從數據庫中讀取記錄的最佳方法是什麼?從數據庫中有效地讀取多個記錄給定數組的記錄ID

$idNumsIWant = {2,4,5,7,9,23,56}; 

顯然遍歷每個ID是不好的,因爲你做ñ查詢:

foreach ($idNumsIWant as $memID) { 
    $DBinfo = mysql_fetch_assoc(mysql_query("SELECT * FROM members WHERE mem_id = '$memID'")); 
    echo "{$DBinfo['fname']}\n"; 
} 

所以,也許最好是使用單一的查詢?

$sqlResult = mysql_query("SELECT * FROM members WHERE mem_id IN (".join(",",$idNumsIWant).")"); 
while ($DBinfo = mysql_fetch_assoc($sqlResult)) 
    echo "{$DBinfo['fname']}\n"; 

但是,當數組有30,000個元素時,此方法縮放嗎?

你如何有效地解決這個問題?

回答

1

我的想法:

第一種方法在處理和磁盤讀取方面成本太高。

第二種方法更高效,您不必擔心太多query size limit(但無論如何請檢查它)。

1

當我必須處理那種情況下,我看到至少有三個或四個可能的解決方案:每個ID

  • 一個請求;正如你所說,這不太好:很多請求;我一般不這樣做
  • 使用你提出的解決方案:對於許多IDS
    • 一個請求,但你不能做一個很長的ID列表:一些數據庫引擎有個限度的數量數據可以在IN()
    • 一個非常大名單傳遞IN()可能不是很好的性能,明智的
    • 所以我通常做一些像X IDS一個請求,並重復這一點。例如,爲了確保與1000個ID相對應的數據,我可以做20個請求,每個請求獲得50個ID的數據(這僅僅是一個例子:基準你的數據庫/表可能是有利的,因爲你的具體情況,因爲它可能取決於幾個因素)
  • 在某些情況下,您還可以重新考慮您的請求:也許您可以通過使用某種連接來避免傳遞這樣的ID列表? (這實際上取決於你需要什麼,你的表的架構,...)

此外,爲方便取邏輯的修改,我會寫的是獲得ID列表的功能,和返回與那些相對應的數據列表。

這樣,你只需要調用這個函數以同樣的方式,你總是得到相同的數據,不必擔心數據是如何獲取的;這將允許您如果需要的話(如果你發現某一天另一種更好的方式)改變取出方法,不破壞任何東西:函數如何作品會改變,但它的接口(輸入/輸出)將保持不變,也不會改變任何事情你代碼的其餘部分:-)

1

如果是我的話,我有那麼大的一個IN子句值列表,我會用一個存儲過程包含我想要的值,並使用一個變量一個函數將它們發送到臨時表中,然後加入它。根據您要發送的值的大小,您可能需要將其分成多個輸入源以進行處理。有沒有什麼方法可以在數據庫中永久存儲值(如果他們經常查詢)?用戶如何挑選30,000個值,他/她肯定不會全部投入?因此,可能有更好的方式來基於聯接和where子句來查詢表。

2

最好的方法最終取決於您的數組中有ID的數量(你顯然不希望一個50MB的SQL查詢發送到服務器,即使在技術上它可能是能夠處理它,沒有太多的麻煩),但主要是關於如何處理結果行。

  • 如果ID的數量是非常低的(比方說,一個幾千頂),一個查詢使用的語法將是完美的WHERE子句。您的SQL查詢將足夠短,以便它可以可靠,高效且快速地傳輸到數據庫服務器。此方法非常適合單個線程遍歷結果記錄。

  • 如果ID數量真的很大,我建議你將ID數組分成幾組,然後運行多個查詢,每個查詢都帶有一組ID。這可能是爲DB服務器重一點,但在應用程序方面,你可以派生幾個線程,並儘快爲他們到達與多個記錄處理,在parrallel方式。

這兩種方法都行得通。

Cliffnotes:對於那種情況下,專注於數據使用,只要數據的提取是不是太大的瓶頸。並分析您的應用程序!

0

通過將字符串分離爲令牌來使用StringTokenizer,您可以更輕鬆地處理這種檢索多個值的數據

相關問題