¿Cómo encuentro efectivamente filas de blobs duplicados en MySQL?
-
11-07-2019 - |
Pregunta
Tengo una tabla de la forma
CREATE TABLE data
{
pk INT PRIMARY KEY AUTO_INCREMENT,
dt BLOB
};
Tiene aproximadamente 160,000 filas y aproximadamente 2GB de datos en la columna de blobs (promedio de 14kb por blob). Otra tabla tiene claves foráneas en esta tabla.
Algo así como 3000 de los blobs son idénticos. Entonces, lo que quiero es una consulta que me dé una tabla de reasignación que me permita eliminar los duplicados.
El enfoque ingenuo tardó aproximadamente una hora en 30-40k filas:
SELECT a.pk, MIN(b.pk)
FROM data AS a
JOIN data AS b
ON a.dt=b.dt
WHERE b.pk < a.pk
GROUP BY a.pk;
Resulta que tengo, por otras razones, una tabla que tiene los tamaños de los blobs:
CREATE TABLE sizes
(
fk INT, // note: non-unique
sz INT
// other cols
);
Al crear índices para ambos fk y otro para sz, la consulta directa toma aproximadamente 24 segundos con 50k filas:
SELECT da.pk,MIN(db.pk)
FROM data AS da
JOIN data AS db
JOIN sizes AS sa
JOIN sizes AS sb
ON
sa.size=sb.size
AND da.pk=sa.fk
AND db.pk=sb.fk
WHERE
sb.fk<sa.fk
AND da.dt=db.dt
GROUP BY da.pk;
Sin embargo, eso está haciendo un análisis completo de la tabla en da (la tabla de datos). Dado que la tasa de aciertos debería ser bastante baja, creo que una exploración de índice sería mejor. Con eso en mente, agregué una tercera copia de datos como una quinta unión para obtener eso, y perdí unos 3 segundos.
Bien, entonces para la pregunta: ¿Voy a ser mucho mejor que la segunda selección? Si es así, ¿cómo?
Un poco de corolario es: si tengo una tabla donde la columna clave se usa mucho pero el resto solo se usa raramente, ¿alguna vez sería mejor agregar otra combinación de esa tabla para alentar una exploración de índice vs . un escaneo completo de la tabla?
Xgc en #mysql@irc.freenode.net señala que agregar una tabla de utilidad como tamaños pero con una restricción única en fk
podría ayudar mucho. Un poco de diversión con los desencadenantes y lo que no puede hacer que no sea tan malo mantenerse actualizado.