Tengo alrededor de 40 millones de filas en una tabla MySQL y quiero copiar esta tabla en otra tabla en la misma base de datos. ¿Cuál es la forma más eficiente de hacer esto? ¿Cuánto tiempo llevará (aprox.)?
mysql
insert
bulk-insert
Devashish Dixit
fuente
fuente
Respuestas:
Supongamos que tienes
mydb.mytb
y quieres crearmydb.mytbcopy
Tengo cinco (5) enfoques para hacer esta copia
ENFOQUE # 1
En el
mysql
cliente, ejecute lo siguienteENFOQUE # 2
ENFOQUE # 3
ENFOQUE # 4
ENFOQUE # 5
ANÁLISIS
Si desea copiar
mydb.mytb
en una tabla ya existentemydb.mytbcopy
, y las dos tablas tienen estructuras idénticas:ENFOQUE # 6
Al igual que #APPROACH 1 , #APPROACH 6 tendría una sola transacción de 40 millones de filas
ENFOQUE # 7
Este enfoque no deja caer la tabla. Simplemente genera los INSERTOS
EPÍLOGO
No puedo darle una estimación de tiempo, ya que no conozco la composición del servidor DB, la estructura de la tabla, el diseño del índice y cosas como estas.
DARLE UNA OPORTUNIDAD !!!
fuente
Las tablas InnoDB, a diferencia de MyISAM *, no pueden "copiarse", como parte de su diccionario de datos (y potencialmente otras estructuras de las que depende la tabla, como el búfer de fusión) se encuentran en la memoria (si el servidor está funcionando) y en el espacio de tabla común / principal, también conocido como ese archivo grande llamado
ibdata1
.Si está utilizando Percona Server> = 5.1 o MySQL> = 5.6, hay soporte para espacios de tablas transportables, lo que le permite exportar e importar tablas directamente desde el sistema de archivos. Aquí está el método para MySQL y para Percona . En ambos casos, se requiere que haya creado la tabla con la
innodb_file_per_table
opción e implica el uso deDISCARD TABLESPACE/IMPORT TABLESPACE
y / o Percona Xtrabakup (si desea que la exportación se realice en línea). Tenga en cuenta que Percona Server o Xtrabakup no están disponibles para Windows.Este método será, hablando en general, tan rápido como copiar el archivo usando los comandos del sistema de archivos (cp, rsync).
Si bien puede haber algunos casos en que esto podría funcionar en MySQL <5.6 (de una manera hacky) para las restauraciones, no funcionará para una copia de la tabla. En esos casos, una forma de hacerlo es usando SQL :
Esto será tan rápido como InnoDB puede ejecutar
Handler_read_rnd_next
yHandler_write
, una vez por fila. Si usa este método, asegúrese de deshabilitar, al menos temporalmente, las opciones de durabilidad y de tener un gran grupo de búferes y un registro de transacciones. En esas circunstancias, puede reducir el tiempo de importación, pero definitivamente no cabe en la memoria por completo, así que espere mucho tiempo. Además, está intentando importar 40 millones de filas en una sola transacción, lo que puede generar problemas.Mi recomendación real, en este segundo caso, sería usar algo como pt-archiver , ya que realizará una operación similar a la que acabo de mencionar, pero se realizará en "fragmentos", evitando la sobrecarga transaccional (puede no será más rápido, pero en caso de falla, no intentará deshacer toda la tabla, demorando para siempre). Para los tamaños de datos que menciona, esta es probablemente la mejor manera de hacerlo.
Una opción final sería exportar e importar utilizando el formato CSV (o TSV) , con una combinación de SELECCIONAR EN SALIDA / mysqldump y CARGAR DATOS / mysqlimport. Esta era una opción muy común si necesitaba concurrencia en ciertas versiones antiguas de mysql, ya que el uso de sql creó bloqueos más grandes (ya no es cierto si se hace correctamente). Como mysqldump / import solo funciona de forma serializada, te recomendaría investigar opciones para paralelizarlo, muy útil para tablas grandes.
En cualquier caso, trate de evitar múltiples oraciones SQL, ya que será su cuello de botella más importante si ejecuta muchas consultas diferentes (que deben ejecutarse, analizarse y optimizarse individualmente).
* Las estructuras MyISAM no se pueden copiar de manera activa, pero es muy fácil sincronizarlas temporalmente en el disco
FTWRL
.fuente
mover datos de una tabla a otra en esquema
create table your_table_name select * from old_schema_table;
fuente