Thank you Rick! You're a super freak! ;-p

This gets me in the vicinity of where I'm trying to go and I learned a few
new tricks with the StartLoop: stuff too! Neat!

d.

> -----Original Message-----
> From: Rick James [mailto:rja...@yahoo-inc.com]
> Sent: Thursday, October 25, 2012 1:54 PM
> To: Daevid Vincent; mysql@lists.mysql.com
> Subject: RE: Help with purging old logs for each customer ID
> 
> If the 90 days is back from MAX(created_on) for a given customer...
>    INDEX(customer_id, created_on)
> will probably be needed.  And that should replace KEY `customers_id`
> (`customer_id`).
> 
> Maybe...
> 
> DELETE FROM customers_log AS a
>     WHERE a.customer_log_id >= @left_off AND a.customer_log_id < @z
>       AND a.created_on <
>              ( SELECT MAX(created_on) FROM customers_log
>                  WHERE customer_id = a.customer_id
>              )
>               - INTERVAL 90 DAY );
> (Since this has the subquery, I would do only 100 at a time, not 1000)
> 
> Or...
> CREATE TEMPORARY TABLE tmp
>     SELECT customer_id, MAX(created_on) - INTERVAL 90 DAY  AS cutoff
>         FROM customers_log
>         GROUP BY customer_id;
> DELETE FROM customers_log AS a
>        JOIN tmp  ON a.customer_id = tmp.customer_id
>     WHERE a.customer_log_id >= @left_off AND a.customer_log_id < @z
>       AND a.created_on < tmp.cutoff;
> 
> If you have millions of rows, a delete without some kind of loop is asking
> for trouble.
> 
> Or...
> Turning things around to base it on customers...
> Loop through customer_ids (yeah, you did not want to do this)
> 
> SELECT @id := 0;
> StartLoop:
>     SELECT @id := customer_id WHERE customer_id > @id ORDER BY customer_id
> LIMIT 1;
>     if @id is NULL, exit
>     DELETE FROM customers_log AS a
>         WHERE a.customer_id = @id
>           AND a.created_on <
>              ( SELECT MAX(created_on) FROM customers_log
>                  WHERE customer_id = @id
>              )
>               - INTERVAL 90 DAY );
> EndLoop.
> 
> Since there is no rush for the purging, there is little need to optimize
it
> other than to keep it from interfering with other queries.  To that end,
the
> compound index I propose is important.
> 
> > -----Original Message-----
> > From: Daevid Vincent [mailto:dae...@daevid.com]
> > Sent: Thursday, October 25, 2012 1:33 PM
> > To: Rick James; mysql@lists.mysql.com
> > Subject: RE: Help with purging old logs for each customer ID
> >
> > Well, the customer_id is relevant in that I want the last 90 days
> > relative to each customer.
> >
> > customer_id = 123 might have logs from jan - mar customer_id = 444
> > might have logs from feb - may
> >
> > So it's a rolling log of THEIR last 90 days from their last log (most
> > recent) back 90 days from there.
> >
> > Does that make more sense?
> >
> > I guess I was trying to avoid looping over every customer ID and
> > computing if I could help it. I thought by using a GROUP BY or
> > something it could group all the logs for a given customer and then
> > trim them that way.
> >
> > But maybe brute force is the way to go?
> >
> > > -----Original Message-----
> > > From: Rick James [mailto:rja...@yahoo-inc.com]
> > > Sent: Thursday, October 25, 2012 1:09 PM
> > > To: Daevid Vincent; mysql@lists.mysql.com
> > > Subject: RE: Help with purging old logs for each customer ID
> > >
> > > Off hand, I would iterate over the PRIMARY KEY, looking at a thousand
> > > rows at a time, DELETEing any that need to be purged.  I would use a
> > > Perl or
> > PHP
> > > loop, or write a stored procedure.  More discussion of "huge deletes"
> > (which
> > > this _could_ be):
> > >     http://mysql.rjweb.org/doc.php/deletebig
> > > (PARTITIONing does not apply in your case, as I understand it.)
> > >
> > > I like the loop:
> > >
> > >     SELECT @z := customer_log_id FROM customers_log LIMIT 1000, 1;
> > >     DELETE FROM customers_log
> > >         WHERE customer_log_id >= @left_off AND customer_log_id < @z
> > >           AND created_on < NOW() - INTERVAL 90 DAY;
> > >     sleep a few seconds (to be a nice guy)
> > >
> > > Plus code to take care of iterating and terminating.
> > >
> > > That loop could be done continually.
> > >
> > > It seems that customer_id is irrelevant??
> > >
> > > > -----Original Message-----
> > > > From: Daevid Vincent [mailto:dae...@daevid.com]
> > > > Sent: Thursday, October 25, 2012 11:46 AM
> > > > To: mysql@lists.mysql.com
> > > > Subject: Help with purging old logs for each customer ID
> > > >
> > > > I have a customer log table that is starting to rapidly fill up (we
> > > > have hundreds of thousands of users, but many are transient, and
> > use
> > > > the service for a few months, or use the free trial and quit, etc.)
> > > >
> > > > CREATE TABLE `customers_log` (
> > > >   `customer_log_id` bigint(20) unsigned NOT NULL auto_increment,
> > > >   `customer_id` int(10) unsigned default '0',
> > > >   `created_on` timestamp NOT NULL default CURRENT_TIMESTAMP on
> > > > update CURRENT_TIMESTAMP,
> > > >   `type`
> > > >
> > enum('View','Action','Admin','Search','Login','Logout','Access','Gen
> > > > era
> > > > l','A
> > > > PI'),
> > > >   `source` enum('web','mobile','system'),
> > > >   `body` text,
> > > >   PRIMARY KEY  (`customer_log_id`),
> > > >   KEY `created_on` (`created_on`),
> > > >   KEY `customers_id` (`customer_id`)
> > > > ) ENGINE=InnoDB
> > > >
> > > > What I'd like to do now is make a 'rolling log' in that I want to
> > > > DELETE any entries older than 90 days for EACH `customer_id`.
> > > >
> > > > I'm not sure how to do that in a query? I'd rather not iterate over
> > > > each customer_id if I can help it.
> > > >
> > > >
> > > >
> > > >
> > > > --
> > > > MySQL General Mailing List
> > > > For list archives: http://lists.mysql.com/mysql
> > > > To unsubscribe:    http://lists.mysql.com/mysql
> > >
> > >
> > > --
> > > MySQL General Mailing List
> > > For list archives: http://lists.mysql.com/mysql
> > > To unsubscribe:    http://lists.mysql.com/mysql


-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/mysql

Reply via email to