2012-03-14 14 views
6

Tengo una tabla con 300 000 registros. En esta tabla tienen duplicae filas y quiero actualizar la columna "bandera"¿Cómo puedo optimizar la consulta de MySQL para la actualización?

TABLA

------------------------------------ 
|number | flag | ... more column ...| 
------------------------------------ 
|ABCD | 0 | ...................| 
|ABCD | 0 | ...................| 
|ABCD | 0 | ...................| 
|BCDE | 0 | ...................| 
|BCDE | 0 | ...................| 

que utilizar esta consulta para la actualización de "bandera" de la columna:

UPDATE table i 
INNER JOIN (SELECT number FROM table 
      GROUP BY number HAVING count(number) > 1) i2 
ON i.number = i2.number 
SET i.flag = '1' 

Esta consulta trabajando muy, muy lentamente (más 600 segundos) para estos 300 000 registros.

¿Cómo puedo optimizar esta consulta?

ESTRUCTURA DE MI TABLA

CREATE TABLE IF NOT EXISTS `inv` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `pn` varchar(10) NOT NULL COMMENT 'Part Number', 
    `qty` int(5) NOT NULL, 
    `qty_old` int(5) NOT NULL, 
    `flag_qty` tinyint(1) NOT NULL, 
    `name` varchar(60) NOT NULL, 
    `vid` int(11) NOT NULL , 
    `flag_d` tinyint(1) NOT NULL , 
    `flag_u` tinyint(1) NOT NULL , 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `pn` (`pn`), 
    KEY `name` (`name`), 
    KEY `vid` (`vid`), 
    KEY `pn_2` (`pn`), 
    KEY `flag_qty` (`flag_qty`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ; 

Si "nombre" es duplicar Quiero actualizar flag_qty

+0

¿Cuál es la estructura de la tabla? ¿Hay una clave principal disponible en esta tabla? – nnichols

+1

¿Cuál es el propósito de establecer esta bandera? ¿Estás haciendo un procesamiento adicional basado en esta bandera? – nnichols

+0

El propósito en este indicador es SI tiene en filas duplicadas de tabla este indicador es 1. Después de eso quiero crear tablas con filas duplicadas y eliminar estas filas de la tabla principal. – dido

Respuesta

2

Si aún no dispone de un índice en number se debe añadir uno -

CREATE INDEX table_number ON table (number); 

ACTUALIZACIÓN Prueba esto -

UPDATE inv t1 
INNER JOIN inv t2 
    ON t1.name = t2.name 
    AND t1.id <> t2.id 
SET t1.flag_qty = 1; 

Usted puede crear la tabla con sólo los duplicados seleccionando esta información directamente en otra tabla en lugar de hacer esta actualización de indicador primero.

INSERT INTO duplicate_invs 
SELECT DISTINCT inv1.* 
FROM inv AS inv1 
INNER JOIN inv AS inv2 
    ON inv1.name = inv2.name 
    AND inv1.id < inv2.id 

Si puede explicar la lógica para lo cual se eliminan las filas de la tabla inv puede ser que todo el proceso se puede realizar en un solo paso.

+0

número de columna es el ÍNDICE – dido

+0

En ese caso, publique la salida de 'MOSTRAR LOS ÍNDICES FROM table_name'. Ejecuté su consulta en filas de 3M en una prueba y regresó en poco más de 1 en mi computadora portátil. Agregar la estructura completa de la tabla (salida de 'SHOW CREATE TABLE table_name') podría ser útil. – nnichols

+0

Agregué una estructura sql de mi tabla. – dido

1

lograr que MySQL EXPLAIN la consulta en su caso. Entonces verás qué indexación mejoraría las cosas.

1

EXPLAIN le mostrará donde es lento y Acá algunas ideas, cómo que mejoran perfomance de:

  • Añadir indexación
  • claves externas
  • Uso InnoDB
  • consulta divide en 2 y procesarlos por separado en el lenguaje que use.
  • escribe la misma idea en el procedimiento MySQL (no estoy seguro, si esto sería rápido).
1

Yo usaría una tabla temporal. 1.) seleccione todos los registros relevantes en una tabla temporal, configure INDEX en id. 2.) actualizar la tabla usando algo como esto

UPDATE table i, tmp_i 
SET i.flag = '1' 
WHERE i.id = tmp_i.id 
1

puede probar (suponiendo VB.net, pero se puede implementar con cualquier lenguaje).

Dim ids As String = Cmd.ExectueScalar("select group_concat(number) from (SELECT number FROM table GROUP BY number HAVING count(number) > 1)") 

Después de obtener la lista de identificadores (separados por comas) que utilice

UPDATE i 
SET i.flag = '1' 
WHERE i.number in (....) 

Puede ser lenta también, pero la primera - SELECT, no va a encerrar a su base de datos y la replicación, etc. .el UPDATE será más rápido.

Cuestiones relacionadas