简体   繁体   English

MySQL触发器会比php更快地检查20多个行吗?

[英]Would a MySQL trigger be faster than php to check for 20+ rows?

At the moment we record a users last 20 media views so that they can have a brief history page of what they've looked at recently. 目前,我们为用户记录最近20次媒体观看,以便他们可以简要回顾他们最近浏览过的内容。

To do this we insert the media ids into a table. 为此,我们将媒体ID插入表中。

To keep the table a small size it's currently only 20 items per user so before inserting the row we check to see how many history ids they currently have in there, if it's less than 20 then we just insert the new row, if it's more than 20 then we have to select the last row and delete it before the new row can be inserted. 为了缩小表格的大小,目前每个用户只有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))");

I'm now converting the site to more modern code and will be using pdo queries, my quesiton is: 我现在正在将该网站转换为更现代的代码,并将使用pdo查询,我的问题是:

Is the above a good way to approach this or should I use another method such as a MySQL trigger on insert? 以上是解决此问题的好方法,还是应该在插入时使用其他方法(例如MySQL触发器)?

If you are really interested in maximum speed, there's also the extremely performant option of not checking how many rows are there in the first place and having a cleanup operation prune them in the background. 如果您真的对最大速度感兴趣,那么还有一个非常高性能的选择,即不首先检查多少行,而在后台进行清理操作来修剪它们。 Whenever you want to insert a new row, simply do so directly. 每当您要插入新行时,只需直接这样做即可。 Whenever you fetch the most recent rows to display, use LIMIT 20 . 每当您获取要显示的最新行时,请使用LIMIT 20

A garbage collector process can run independently of this as often as you want it to, looking for users with more than 20 history records and deleting the oldest appropriately. 垃圾收集器进程可以独立于此运行,您可以根据需要运行它,查找具有20多个历史记录的用户,并适当地删除最旧的记录。 This way you have a guaranteed lower bound for recent history items (provided they have been created at some point) and an unlimited but quite low in practice amount of old history records awaiting pruning. 这样,您就可以保证最近历史记录项的下限(前提是它们是在某个时候创建​​的),并且在实践中可以无限量但实际上数量很低的旧历史记录等待修剪。 You can decide on the collection frequency as you prefer. 您可以根据需要决定收集频率。

On the other hand, if it's not absolute performance that you are after then a check from PHP should be fine -- provided that you change it to do SELECT COUNT(*) FROM mediatable WHERE userId = $userId when looking how many ids already exist. 另一方面,如果不是绝对的性能,那么从PHP进行检查应该没问题-前提是您更改它以在查看已有ID时SELECT COUNT(*) FROM mediatable WHERE userId = $userId进行SELECT COUNT(*) FROM mediatable WHERE userId = $userId This way it's also easier by far to modify your retention strategy down the road. 这样,到目前为止,修改保留策略也更加容易。

Update: Garbage collection strategies to consider 更新:要考虑的垃圾收集策略

  1. Scheduled GC: Collection happens periodically, most likely on a fixed schedule. 预定的GC:定期进行收集,最有可能按固定的时间表进行。 Typically this is implemented as a cron job or scheduled task, depending on OS. 通常,根据操作系统,这可以实现为cron作业或计划任务。 Advantages include reliability and the option to use historical data to significantly decrease the standard deviation of items waiting to be pruned. 优点包括可靠性和使用历史数据的选项,可以显着降低等待修剪的物品的标准偏差。 Additionally, cleanup is not associated with (and should not block) any one user request; 此外,清理不与任何一个用户请求相关联(并且不应阻止)。 this eliminates the (typically rare) occasion where a user has to wait for GC to be completed before their content becomes available. 这样就消除了(通常很少见)用户必须等待GC完成才能获得其内容的情况(这种情况很少见)。
  2. Probabilistic GC: Collection is triggered randomly. 概率GC:随机触发收集。 Your application specifies a set of actions that can trigger GC (eg creating a new history item) and a probability for GC to be triggered whenever any action in the set occurs; 您的应用程序指定了一组可触发GC的操作(例如,创建新的历史记录项目),以及在该组中发生任何操作时都会触发GC的可能性; collection can happen as part of processing the action, or the collector can be a separate process that is launched on demand. 收集可以作为处理操作的一部分进行,或者收集器可以是按需启动的单独过程。 The most significant advantage is that no setup external to your application is required, which may not be as important if your app is not meant to be widely distributed. 最显着的优点是,无需在应用程序外部进行任何设置,如果您的应用程序不打算广泛分布,则可能没有那么重要。 Adjusting the GC probability while taking into account the mean number of triggering actions per unit of time allows you to target (albeit coarsely) a desired interval between successive collections. 在考虑到每单位时间触发动作的平均数量的同时调整GC的概率,您可以(尽管粗略地)确定连续采集之间的期望间隔。

The following will insert a new row or reuse an existing id if a user has more than 20 rows inserted already. 如果用户已插入20行以上,则以下内容将插入新行或重用现有ID。 The query uses the oldest existing id for this user. 该查询为此用户使用最早的现有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
");

The best you can do is , make one stored procedure, just pass it your new data, and max length 最好的办法是,创建一个存储过程,将新数据传递给它,并且最大长度
max length because, now its 20, going larger, may need to be changed, so dynamic is better 最大长度,因为现在它的20会变大,可能需要更改,所以动态效果更好
Triggers are also good, but Precompiled Procedures, would better when comparing in term of speed and customization. 触发器也不错,但是在速度和自定义方面进行比较时,预编译过程会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM