简体   繁体   English

MySQL事件-性能和局限性

[英]MySQL events - performance and limitations

I have set-up a simple event that runs every hour and adds a record like this: 我设置了一个每小时运行一次的简单事件,并添加了一条记录,如下所示:

ON SCHEDULE EVERY 1 HOUR STARTS '2015-01-01 00:00:00'
DO
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE a INT;
    DECLARE cursor_1 CURSOR FOR SELECT item_id FROM item WHERE NOW()>expiration_date AND has_expired = 0;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cursor_1;

    read_loop: LOOP
      FETCH cursor_1 INTO a;
       IF done THEN
         LEAVE read_loop;
       END IF;
       UPDATE item SET has_expired=1 WHERE quote_id=a;
       INSERT INTO item_log (item_id, message) VALUES (a, 'Item is now expired');
    END LOOP;
  END

This thing runs 24 times a day and it works as expected, however, there is another idea to create events dynamically and attach them with a given record, eg 这个东西一天运行24次,并且可以按预期运行,但是,还有另一个想法可以动态创建事件并将它们附加到给定的记录中,例如

ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 3 WEEK
DO 
BEGIN
   UPDATE item SET has_expired=1 WHERE item_id=232;
   INSERT INTO item_log (item_id, message) VALUES (232, 'Item is now expired');
END

Of course the above would have different values of interval and ids, but that would mean that there are possibly 1000s or tens of thousands of events. 当然,以上内容将具有不同的interval和id值,但这意味着可能有1000或数万个事件。

Now, would that be a problem? 现在,这会有问题吗? Limitations and performance wise? 限制和性能明智吗? I can imagine that if there are no records, or just few created a month then first approach will be constantly running for nothing. 我可以想象,如果没有记录,或者只有一个月创建了几个记录,那么第一种方法将一无所有。 However if there will be few items added an hour, then it will mean that DB could reach thousands of one-time events. 但是,如果一个小时后添加的项目很少,那么这意味着DB可以达到数千个一次性事件。 Would that not cause problems of its own? 那会不会引起自己的问题?

Would you like to run that 100% faster? 您想以100%的速度运行吗? Get rid of it. 摆脱它。 Instead, have SELECTs include the clause AND (expiration_date < NOW()) 而是让SELECT包含子句AND (expiration_date < NOW())

OK, so you asked about the code. 好的,所以您询问了代码。 Here are some comments: 这里有一些评论:

The UPDATE and INSERT need to be in a transaction. UPDATE和INSERT需要处于事务中。

The SELECT needs FOR UPDATE and should be in the transaction, too. SELECT需要FOR UPDATE,并且也应该在事务中。 But this is less important because, unless you ever change expiration_date, it never matters. 但这并不那么重要,因为除非您更改expiration_date,否则它就无关紧要。

Cursors suck, performance-wise. 在性能方面,游标很烂。 Select 100 rows to purge, then run one UPDATE and one INSERT. 选择要清除的100行,然后运行一项UPDATE和一项INSERT。

Scanning the table for this flag will be a slow "table scan" unless you have an index starting with expiration_date. 除非您有以expiration_date开头的索引,否则扫描表中的该标志将是一个缓慢的“表扫描”。

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

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