2011-03-13 71 views
1

我怎樣才能優化這個MySQL查詢訪問兩個表,每個表有1000多萬行?訪問超過1000萬行的MySQL表=錯誤:連接太多

下面的查詢要做的是,它得到所有從「用戶」表中的ID不上「客人」表中存在。這將會返回超過數十萬行,因此我們將其限制爲每次運行至少獲得5000個ID。有沒有更好的方法來運行,這樣我們就可以在每次運行中完成更多的工作。

$before = date here before in time; 
$now = date now; 

$query="SELECT users.id 
    FROM users 
    LEFT JOIN guests ON guests.id = users.id  
    WHERE guests.id IS NULL AND (users.in >= '$before' AND users.in <= '$now') 
    LIMIT 0,5000"; 

在我們知道guest表上不存在哪些ID後,我們必須刪除users表中的那些行。所以這意味着它會運行另外5000個刪除查詢來刪除所有這些ID。

如果我們運行包含超過1000萬行數據的兩個表我們的服務器返回了它有太多的連接和MySQL服務器之前,可以重新啓動它不再被訪問的錯誤這個過程。但是,如果我們對兩個包含數千行的表執行相同的過程,它不會遇到此問題,但仍需要一些時間。

爲什麼會出現這種情況,我們怎麼能避免這種情況的同時完全優化這個過程。

回答

1

2件事 - 檢查你的軟件如何處理MySQL連接。看起來它打開一個持久連接,然後不重用它,並且在每個查詢之前都有一個新的連接。

二 - 您可以修改您的查詢做一個聲明,而不是運行在每個用戶一個單獨的查詢。這樣只需要一個連接,所有的處理都將在MySQL端,這將進一步優化。

編輯:您可以檢查的另一件事是在您的查詢上運行EXPLAIN,以確保您設置了所有正確的索引(如果選擇零件現在運行緩慢)。

+0

它沒有使用持續連接。令我難以置信的是,在MySQL的進程列表中,在我上面發佈的主要SQL查詢之後有很多SELECT查詢。此選擇查詢選擇訪客表中的ID。 LEFT JOIN或任何JOIN語句是否執行子選擇查詢? LEFT JOIN是否可能導致「連接太多」錯誤? – officeboi101 2011-03-13 16:09:46

+0

@officeboi - 不,那是不可能的。你用什麼軟件/語言/庫?它可能是你的圖書館通過單獨的選擇檢索額外的信息......也許這是相同的庫造成額外的連接... – Sergey 2011-03-13 21:29:05

0

警告:測試此查詢實時數據之前運行。我不要求任何數據丟失的責任

DELETE 
    u 
FROM 
    users AS u 
LEFT JOIN 
    guests AS g 
ON g.id = u.id 
WHERE 
    g.id IS NULL 
    AND (users.in >= '$before' AND users.in <= '$now') 

至於你的問題的核心(連接過多)我懷疑你的PHP腳本開始在循環新的連接永遠ID將被刪除。

+0

我做了一個簡單的PHP測試腳本只是爲了獲取用戶表中的ID客人桌上不存在。這是正常的 - 使用正常連接(不是持久性)連接,然後使用上面的SQL查詢進行SELECT,然後斷開連接並使用PHP輸出結果。我仍然遇到同樣的問題,它給了我「太多連接」的錯誤。我甚至將結果限制在2500,而且還是一樣的。在腳本運行時,也沒有人可以訪問MySQL數據庫。 JOIN語句是否可能導致連接錯誤太多而導致子選擇? – officeboi101 2011-03-13 16:17:03

+0

第一個查詢在一個連接中運行。它不會爲子查詢創建額外的連接。 – Mchl 2011-03-14 07:27:41