2012-05-29 18 views
1

目前我們記錄了用戶最近20次媒體視圖,以便他們可以簡要記錄他們近期看到的內容。MySQL觸發器會比php更快檢查20多行嗎?

爲此,我們將媒體ID插入表中。

爲了保持表格的小尺寸,目前每個用戶只有20個項目,所以在插入行之前,我們檢查一下他們當前有多少歷史ID,如果它小於20,那麼我們只插入新行,如果它超過20,那麼我們必須選擇最後一行並刪除它,然後才能插入新行。

$historyResult = mysql_query("SELECT id FROM mediatable WHERE userId = $userId ORDER BY id ASC"); 

if(mysql_num_rows($historyResult) >= 20) 
{ 
    $historyResult = mysql_query("SELECT id FROM mediatable WHERE userId = $userId ORDER BY id ASC LIMIT 1"); 
    $historyRow = mysql_fetch_row($historyResult); 
    mysql_query("DELETE FROM mediatable WHERE id = '$historyRow[0]'"); 
} 

mysql_query("INSERT INTO mediatable (userId, mediaId) VALUES ($userId, $mediaId))"); 

我的網站現在轉換爲更現代的代碼,將使用PDO查詢,我的quesiton是:

是上面的一個好辦法解決這個或我應該用另一種方法如插入MySQL觸發器?

+0

你也可以嘗試每小時做一次cron,而不是浪費CPU每次調用。 – Jonathan

回答

7

如果您真的對最高速度感興趣,還有非常高性能的選項,無法檢查首先有多少行,並有清理操作在後臺修剪它們。無論何時你想插入一個新的行,只需直接進行。無論何時獲取最近要顯示的行,請使用LIMIT 20

垃圾收集器進程可以獨立於此運行,只要您需要,可以查找具有20多條歷史記錄的用戶並適當刪除最早的那個。通過這種方式,您可以保證最近歷史記錄的下限(假設它們已經在某個時間點創建),並且在等待修剪的舊歷史記錄的實踐量中的數量是無限的,但卻很低。您可以根據自己的喜好決定收集頻率。另一方面,如果它不是絕對的性能,那麼您應該檢查PHP的支票應該沒問題 - 只要您在查看已存在多少個ID時將其更改爲執行SELECT COUNT(*) FROM mediatable WHERE userId = $userId即可。通過這種方式,您可以更輕鬆地修改您的保留策略。

更新:垃圾收集策略考慮

  1. 計劃GC:收集週期性發生,最有可能在一個固定的時間表。通常,這取決於操作系統,以cron作業或計劃任務的形式實現。優點包括可靠性和使用歷史數據顯着降低等待修剪的項目的標準偏差的選項。此外,清理不與任何一個用戶請求相關聯(並且不應該阻止);這消除了用戶必須等待GC完成纔可以完成內容(通常很少)的情況。
  2. 概率GC:採集是隨機觸發的。您的應用程序指定一組可觸發GC的操作(例如,創建新的歷史記錄項)以及集合中發生任何操作時觸發GC的概率;收集可以作爲處理動作的一部分而發生,或者收集器可以是根據需要啓動的獨立過程。最重要的優勢是不需要外部應用程序的設置,如果您的應用程序不是廣泛分佈的,這可能並不重要。在考慮到每單位時間的平均觸發動作次數的同時調整GC概率允許您針對(儘管粗略地)連續收集之間的期望間隔。
+0

您能詳細闡述垃圾收集器的工作原理嗎?它是由cron在特定時間間隔運行的腳本嗎? –

+0

@ConstantineLoukas:添加了一個新的部分,它提供了幾個選項。 – Jon

0

你能做的最好的是,讓一個存儲過程,只是通過其新的數據,而最大長度
最大長度,因爲現在它的20,去較大,可能需要改變,所以動態更好
觸發器也很好,但預編譯過程,在速度和定製方面進行比較時會更好。

1

如果用戶已經插入了超過20行,以下將插入新行或重新使用現有ID。該查詢使用此用戶最舊的現有ID。

mysql_query(" 
INSERT INTO mediatable (id, userId, mediaId) 
    SELECT m.idd, d.u, d.m 
    FROM 
     (SELECT " . $userId . " u, " . $mediaId . " m FROM dual) d LEFT JOIN (
        SELECT userid u, MIN(id) idd FROM mediatable 
        WHERE 
         userid = " . $userId . " 
        GROUP BY 
         userid 
        HAVING COUNT(*) > 20 
       ) m ON d.u = m.u 
"); 
+0

好的,這是我的一個相對較好的答案,因爲它總是會重複使用最舊的ID,這不正是我想要的。但是,速度在這裏:-) 一個非常簡單的解決方法是添加一個日期字段。 – Sebas