2010-03-20 34 views
32

¿Alguien me puede decir cómo agregar una clave en MySQL? Tengo 500,000,000 filas en una base de datos, trans, con columnas i (INT NO SEÑALADO), j (INT NO SEÑALADO), nu (DOBLE), A (DOBLE). Intento indexar una columna, p.MySQL: ¿cuánto tiempo crear un índice?

ALTER TABLE trans ADD KEY idx_A (A); 

y espero. Para una tabla de 14,000,000 filas, tomó aproximadamente 2 minutos para ejecutar en mi MacBook Pro, pero para todo el medio billón, está tomando 15 horas y contando. ¿Estoy haciendo algo mal, o simplemente soy ingenuo acerca de cómo la indexación de una base de datos escala con el número de filas?

+0

es posible que desee ver en división (división de la base de datos) su tabla –

Respuesta

27

Hay un par de factores a considerar:

  • La clasificación es una operación N.log (N).
  • El género para las filas de 14M podría caber en la memoria principal; el tipo con filas de 500M probablemente no, por lo que el género se derrama en el disco, lo que ralentiza enormemente las cosas.

Dado que el factor es de aproximadamente 30 en tamaño, el tiempo nominal de clasificación para el conjunto de datos grandes sería del orden de 50 veces más, menos de dos horas. Sin embargo, necesita 8 bytes por valor de datos y otros 8 bytes de sobrecarga (es una suposición - sintonizar mySQL si sabe más acerca de lo que almacena en un índice). Por lo tanto, 14M × 16 ≈ 220 MB de memoria principal. Pero 500M × 16 ≈ 8 GB de memoria principal. A menos que su máquina tenga tanta memoria de sobra (y MySQL está configurado para usarla), entonces el gran tipo se está volcando en el disco y eso representa gran parte del resto del tiempo.

+1

Muchas gracias, eso tiene sentido para mí, solo tengo 4 GB. Parece que dividir (¿partición?) Los datos como se sugirió anteriormente tiene mucho sentido. – xnx

+0

¿dividiste tu mesa? cuánto tiempo tomó? – juanpastas

2

Según mi experiencia: si el hardware puede soportarlo, la indexación de tablas grandes con MySQL generalmente se escala bastante linealmente. Lo he intentado con tablas de aproximadamente 100,000,000 filas hasta ahora, pero no en una notebook, principalmente en servidores fuertes.

Supongo que depende principalmente de los factores de hardware, el tipo de motor de tabla que está utilizando (MyIsam, INNO, o lo que sea) y un poco si la tabla está en uso en el medio. Cuando lo estaba haciendo, el uso del disco subía bastante alto, a diferencia del uso de la CPU. No estoy seguro sobre los discos duros de la MacBook, pero supongo que no son los más rápidos.

Si tiene tablas MyISAM, tal vez eche un vistazo más de cerca a los archivos de índice en el directorio de la tabla y vea cómo cambia con el tiempo.

+0

Gracias por la respuesta rápida, Björn. Seguí tu sugerencia. Lo tomo los archivos # sql-a8_6.MYD (actualmente 7455506432 bytes) y # sql-a8_6.MYI (actualmente 2,148,865,024 bytes) son la nueva versión de la base de datos está construyendo y el índice solicité respectivamente? Entonces, si la tabla original es trans.MYD (12,645,156,375 bytes) ¿Tengo un 60% de descuento? Está empezando a parecer que sería mejor dividir la gran mesa en tablas de 20 o más pequeñas. Gracias, Christian – xnx

+0

En general, debería ser. Bueno, todo depende de lo que quieras hacer con esa cantidad de datos. 500.000.000 filas son muchas, por lo que si desea realizar informes sofisticados posteriormente, intente minimizar los datos. O intenta dividirlo, o toma un botín en las funciones de partición de MySQL (desde la versión 5.1). – Bjoern

5

En primer lugar, la definición de su tabla podría hacer una gran diferencia aquí. Si no necesita los valores NULL en sus columnas, defínelos NOT NULL. Esto ahorrará espacio en el índice, y presumiblemente tiempo al crearlo.

CREATE TABLE x ( 
    i INTEGER UNSIGNED NOT NULL, 
    j INTEGER UNSIGNED NOT NULL, 
    nu DOUBLE NOT NULL, 
    A DOUBLE NOT NULL 
); 

En cuanto al tiempo necesario para crear los índices, esto requiere una exploración de tabla y se mostrará como REPAIR BY SORTING. Debería ser más rápido en su caso (es decir, un conjunto de datos masivo) crear una nueva tabla con los índices requeridos e insertar los datos en ella, ya que esto evitará la operación REPAIR BY SORTING ya que los índices se crean secuencialmente en la inserción. Hay un concepto similar explicado en this article.

CREATE DATABASE trans_clone; 
CREATE TABLE trans_clone.trans LIKE originalDB.trans; 
ALTER TABLE trans_clone.trans ADD KEY idx_A (A); 

Entonces la escritura la inserción en trozos (según el artículo), o volcar los datos utilizando MYSQLDUMP:

mysqldump originalDB trans --extended-insert --skip-add-drop-table --no-create-db --no-create-info > originalDB .trans.sql 
mysql trans_clone < originalDB .trans.sql 

Se trata de introducir los datos, pero no requerirá una reconstrucción de índices (índice se crea a medida que se inserta cada fila) y debe completarse mucho más rápido.

+1

Tenga en cuenta que en lugar de hacer un 'mysqldump' y una restauración que requeriría al menos un bloqueo de lectura de tabla continuo durante la duración del proceso, podría usar [pt-online-schema-change] (http: //www.percona .com/doc/percona-toolkit/2.2/pt-online-schema-change.html) de Percona Toolkit: se encargaría de la creación y copia de datos en múltiples pasadas, eliminando el requisito de bloqueo continuo. –

0

Así que teóricamente si Ordenación de paso es un (a) el funcionamiento N.log, particionar su mesa grande se ahorraría tiempo en la operación

ganancia Alrededor del 30% para una mesa de 500 000 000 filas partitionned en 100 archivos iguales: porque 500 000 000 * log (500 000 000) = 4 349 485 002 y 100 * (500 000 000/100 * LOG (500 000 000/100)) = 3 349 485 002

Cuestiones relacionadas