2010-09-13 11 views
23

truncar -> esto restablece toda la tabla, ¿hay alguna forma de truncar para restablecer registros particulares/condiciones de verificación.Truncar con la condición

Por ejemplo: quiero restablecer todos los datos y mantener los últimos 30 días dentro de la tabla.

Gracias.

Respuesta

38

No, TRUNCATE es todo o nada. Puede hacer un DELETE FROM <table> WHERE <conditions> pero esto pierde las ventajas de velocidad de TRUNCATE.

+0

, gracias, asumiendo esa condición, ¿Cómo puedo evitar últimos 10 datos de días y elimine el resto (por ejemplo, la tabla tiene 10 millones de registros) de manera optimizada. – Sharpeye500

+1

La velocidad de TRUNCATE se debe a que no escribe en los registros –

21

La respuesta corta es sin: MySQL hace no le permiten añadir una cláusula WHERE a la declaración TRUNCATE. Aquí está MySQL's documentation sobre la declaración TRUNCATE.

Pero la buena noticia es que puede (algo) solucionar esta limitación.

simple, seguro, limpio pero la solución lenta usando DELETE

En primer lugar, si la tabla es lo suficientemente pequeño, sólo tiene que utilizar la declaración DELETE (que tenía que ser mencionado):

1. LOCK TABLE my_table WRITE; 
2. DELETE FROM my_table WHERE my_date<DATE_SUB(NOW(), INTERVAL 1 MONTH); 
3. UNLOCK TABLES; 

Las declaraciones LOCK y UNLOCK no son obligatorias, pero acelerarán las cosas y evitarán posibles bloqueos.

Desafortunadamente, esto será muy lento si su tabla es grande ... y ya que está considerando usar la declaración TRUNCATE, supongo que es porque su tabla es grande.

Así que aquí es una manera de solucionar el problema con la TRUNCATE declaración:

solución simple, rápido, pero no seguro utilizando TRUNCATE

1. CREATE TABLE my_table_backup AS 
     SELECT * FROM my_table WHERE my_date>=DATE_SUB(NOW(), INTERVAL 1 MONTH); 
2. TRUNCATE my_table; 
3. LOCK TABLE my_table WRITE, my_table_backup WRITE; 
4. INSERT INTO my_table SELECT * FROM my_table_backup; 
5. UNLOCK TABLES; 
6. DROP TABLE my_table_backup; 

Desafortunadamente, esta solución es un poco peligroso si otros procesos están insertando registros en la tabla al mismo tiempo:

  • any re el cable insertado entre los pasos 1 y 2 se perderá
  • la instrucción TRUNCATE restablece el contador AUTO-INCREMENT a cero. Por lo tanto, cualquier registro insertado entre los pasos 2 y 3 tendrá un ID que será más bajo que los ID anteriores e incluso podría entrar en conflicto con los ID insertados en el paso 4 (tenga en cuenta que el contador AUTO-INCREMENT volverá al valor correcto después del paso 4).

Desafortunadamente, no es posible bloquear la mesa y truncarla. Pero podemos (de alguna manera) trabajar alrededor de esa limitación usando RENAME.

solución de medio sencillo, rápido, seguro, pero ruidoso usando TRUNCATE

1. RENAME TABLE my_table TO my_table_work; 
2. CREATE TABLE my_table_backup AS 
    SELECT * FROM my_table_work WHERE my_date>DATE_SUB(NOW(), INTERVAL 1 MONTH); 
3. TRUNCATE my_table_work; 
4. LOCK TABLE my_table_work WRITE, my_table_backup WRITE; 
5. INSERT INTO my_table_work SELECT * FROM my_table_backup; 
6. UNLOCK TABLES; 
7. RENAME TABLE my_table_work TO my_table; 
8. DROP TABLE my_table_backup; 

Esto debe ser completamente seguro y bastante rápido. El único problema es que otros procesos verán desaparecer la tabla my_table durante unos segundos. Esto puede llevar a que se muestren errores en los registros en todas partes. Entonces, es una solución segura, pero es "ruidosa".

Descargo de responsabilidad: No soy un experto en MySQL, por lo que estas soluciones podrían ser realmente asquerosas. La única garantía que puedo ofrecer es que funcionen bien para mí. Si algún experto puede comentar sobre estas soluciones, le agradecería.

+0

Excelente respuesta y buena forma de trabajar con las limitaciones. Gracias. –

0

Puede simplemente exportar la tabla con una cláusula de consulta usando datapump e importarla de nuevo con table_exists_action = replace clause. Se reducirá y recreará su mesa y tomará menos tiempo. Por favor, lea sobre esto antes de implementarlo.

0

Como respuesta a su pregunta: "quiero restablecer todos los datos y mantener los últimos 30 días dentro de la tabla".

puede crear un evento. Comprobar https://dev.mysql.com/doc/refman/5.7/en/event-scheduler.html

Por ejemplo:

CREATE EVENT DeleteExpiredLog 
ON SCHEDULE EVERY 1 DAY 
DO 
DELETE FROM log WHERE date < DATE_SUB(NOW(), INTERVAL 30 DAY); 

se ejecutará una limpieza diaria de la tabla, manteniendo los últimos 30 días los datos disponibles