2010-09-08 16 views
7

Mi aplicación necesita sondear una base de datos MySQL para nuevas filas. Cada vez que se agregan nuevas filas, se deben recuperar. Estaba pensando en crear un disparador para colocar referencias a filas nuevas en una tabla separada. La tabla original tiene más de 300,000 filas.¿Cuál es la forma más rápida de sondear una tabla MySQL para nuevas filas?

La aplicación está construida en PHP.

Algunas buenas respuestas, creo que la pregunta merece una recompensa.

+2

IMO, si es posible, cualquier capa que use para insertar, es decir, los servicios que envuelven operaciones CRUD, debe 'notificar' su aplicación después de una inserción. De esta manera no estás constantemente sondeando. – Alex

+0

@Alex: son dos aplicaciones independientes diferentes. La segunda aplicación solo lee desde la base de datos. – HyderA

+1

Diría que el disparador DESPUÉS DE INSERTAR sería perfecto, impleméntelo en el nivel MySQL y deje que los scripts sondeen y limpien las nuevas entradas en la otra tabla. De esa forma, incluso forzar otra identificación (no autoincrement) aún funcionaría. – Wrikken

Respuesta

7

Para aplicaciones externas encuentro utilizando una columna timestamp es un método más robusto que es independiente de la identificación automática y otras cuestiones claves primarias

agregar columnas a las tablas tales como:

insertedOn TIMESTAMP DEFAULT CURRENT_TIMESTAMP 

o para realizar un seguimiento de las inserciones y actualizaciones

updatedOn TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 

En la externa l aplicación todo lo que necesita hacer es rastrear la última marca de tiempo cuando realizó una encuesta. Luego seleccione de esa marca de tiempo hacia adelante en todas las tablas relevantes. En tablas grandes puede necesitar indexar la columna de marca de tiempo

+0

La indexación de dicho campo * siempre * será beneficiosa, no solo en el caso de tablas grandes. +1 de todos modos. –

+0

La indexación suele ser beneficiosa. Hay muchos casos de uso cuando la carga del índice no vale la pena. Normalmente, una tabla que tiene muchas inserciones y elimina entre cada selección basada en TIMESTAMP, y la selección basada en TIMESTAMP se realiza con poca frecuencia – TFD

+1

Algo a tener cuidado con esta solución: si la aplicación que realiza la encuesta obtiene los cambios en lotes (por ejemplo, 'SELECT * FROM TABLE WHERE updatedOn>: LAST_TIMESTAMP ORDER BY updateOn LIMIT 100') y existe la posibilidad de que se actualice el tamaño del lote de una vez (por ejemplo, 'UPDATE TABLE SET COLUMN = 'VALUE' WHERE OTHER_COLUMN = 'ALGO QUE SELECCIONARÁ CIENTOS DE ROWS'') entonces perderás filas. – ICR

3

Usted puede utilizar la siguiente instrucción para averiguar si un nuevo disco se insertó en la tabla:

select max(id) from table_name 

reemplazando el nombre de la clave primaria y nombre de tabla en la declaración anterior. Mantenga el valor máximo (id) en una variable temporal y recupere todos los registros nuevos entre este y el último valor máximo (id) guardado. Después de obtener los nuevos registros, establezca el valor máximo (id) en el que obtuvo de la consulta.

+1

¿Por qué no seleccionar * de table_name donde id>: max –

0

suponiendo que tiene una identificación u otros datos que siempre crecen, debe hacer un seguimiento de su aplicación php de la última identificación recuperada.

que funcionaría para la mayoría de los escenarios. A menos que estés en el campamento de tiempo real, no creo que necesites nada más que eso.

0

Haría algo como esto. Por supuesto, esto supone que ID es una ID numérica creciente. Y cómo usted almacena su "ubicación actual" en la base de datos depende de usted.

<? 
$idFile = 'lastID.dat'; 

if(is_file($idFile)){ 
    $lastSelectedId = (int)file_get_contents($idFile); 
} else { 
    $lastSelectedId = 0; 
} 

$res = mysql_query("select * from table_name where id > {$lastSelectedId}"); 

while($row = mysql_fetch_assoc($res)){ 
    // Do something with the new rows 

    if($row['id']>$lastSelectedId){ 
     $lastSelectedId = $row['id']; 
    } 
} 

file_put_contents($idFile,$lastSelectedId); 

?> 
0

Yo coincidiría con la respuesta de TFD acerca de hacer un seguimiento de una marca de tiempo en un archivo/tabla separado y luego buscar todas las filas más nuevas que esa. Así es como lo hago para una aplicación similar.

Su aplicación consultar una sola fila de tabla (o archivo) para ver si una marca de tiempo ha cambiado desde el almacenamiento local no debería ser un gran golpe de rendimiento. Entonces, obtener nuevas filas de la tabla de 300k filas basadas en la marca de tiempo debería volver a estar bien, suponiendo que la marca de tiempo esté correctamente indexada.

Sin embargo, al leer su pregunta, tenía curiosidad por saber si los disparadores de Mysql pueden hacer llamadas al sistema, por ejemplo, un script de php que haría algo de trabajo pesado. Resulta they can usando el sys_exec()User-Defined Function. Puede usar esto para hacer todo tipo de procesamiento pasando los datos de fila insertados, esencialmente teniendo una notificación instantánea de inserciones.

Por último, a word of caution sobre el uso de desencadenadores para llamar a aplicaciones externas.

0

Una opción podría ser utilizar una instrucción INSERT INTO SELECT. Tomando de las sugerencias utilizando las marcas de tiempo para tirar de las últimas filas, se podía hacer algo así ...

INSERT INTO t2 (
    SELECT * 
    FROM t1 
    WHERE createdts > DATE_SUB(NOW(), INTERVAL 1 HOUR) 
); 

esto tomaría todas las filas insertadas en la hora anterior e insertarlos en la tabla 2. Usted podría tener un script ejecuta esta consulta y la ejecuta cada hora (o el intervalo que necesite).

Esto simplificará drásticamente su script PHP para tirar filas ya que no necesita iterar sobre ninguna fila. También se deshace de tener que realizar un seguimiento de la última identificación de inserción.

La solución propuesta por Fanis también parece que podría ser interesante también.

Como nota, la consulta de selección en la inserción anterior solo puede ajustarse para insertar ciertos campos. Si sólo necesita ciertos campos, lo que tendría que especificarlos en el inserto así ...

INSERT INTO t2 (field1, field2) (
    SELECT field1, field2 
    FROM t1 
    WHERE createdts > DATE_SUB(NOW(), INTERVAL 1 HOUR) 
); 
1

Crear un PHP Daemon para controlar el tamaño del archivo de MySQL tabla, si el tamaño cambia de consulta para los nuevos registros, si el nuevo registros encontrados ejecutan el siguiente proceso.

Creo que hay un daemon PEAR activo que puede configurar fácilmente para controlar el tamaño del archivo de tabla MySQL y arrancar su script.

+1

No estoy seguro de MySQL, pero generalmente el espacio de la tabla se asigna en fragmentos, por lo que una vez que se ha hecho una asignación, se podrían agregar varias filas antes de que surja la necesidad de otra asignación. – pascal

+0

Muchas tablas están en el mismo archivo si se usa innodb. – frodeborli

Cuestiones relacionadas