Investigué mucho sobre cómo mantener índices en MySQL para evitar la fragmentación y optimizar de alguna manera la ejecución de algunas consultas.
Estoy familiarizado con esa fórmula que calcula la relación entre el espacio máximo disponible para una tabla VS el espacio utilizado por datos e índices.
Sin embargo, mis preguntas principales siguen sin respuesta. Quizás esto se deba al hecho de que estoy familiarizado con el mantenimiento de índices en SQL Server, y tiendo a pensar que en MySQL debería ser de alguna manera similar.
En el servidor SQL, puede tener varios índices, y cada uno de ellos puede tener diferentes niveles de fragmentación. Luego puede elegir uno y realizar una operación 'REORGANIZAR' o 'RECONSTRUIR' en ese índice en particular, sin afectar el resto.
Que yo sepa, no existe una "fragmentación de la tabla" como tal, y SQL Server no proporciona ninguna herramienta para corregir la "fragmentación de la tabla". Lo que sí proporciona son herramientas para verificar la fragmentación del índice (entendida como la relación entre el número de páginas utilizadas por un índice VS la plenitud de esa página y la contigüidad), así como la fragmentación interna y externa.
Todo eso es bastante sencillo de entender, al menos para mí.
Ahora, cuando llega el turno de mantener índices en MySQL, solo existe el concepto de 'fragmentación de tabla', como se mencionó anteriormente.
Una tabla en MySQL puede tener varios índices, pero cuando compruebo la 'relación de fragmentación' con esa famosa fórmula, no veo la fragmentación de cada índice, sino la tabla en su conjunto.
Cuando quiero optimizar los índices en MySQL, no elijo un índice particular para operar (como en SQL Server). En cambio, hago una operación 'OPTIMIZAR' en toda la tabla, que presumiblemente afecta a todos los índices.
Cuando la tabla está optimizada en MySQL, la relación entre el espacio utilizado por los datos + índices VS el espacio general se reduce, lo que sugiere algún tipo de reorganización física en el disco duro, lo que se traduce en una reducción del espacio físico. Sin embargo, la fragmentación del índice no se trata solo del espacio físico, sino de la estructura del árbol que ha cambiado con el tiempo debido a inserciones y actualizaciones.
Finalmente, obtuve una tabla en InnoDB / MySQL. Esa tabla tiene 3 millones de registros, 105 columnas y 55 índices. Es 1.5GB excluyendo índices, que son 2.1GB.
Esa tabla está siendo golpeada miles de veces al día para actualizar, insertar (en realidad no eliminamos registros).
Esa tabla ha sido creada años atrás y sé con certeza que nadie está manteniendo índices en absoluto.
Esperaba encontrar una gran fragmentación allí, pero cuando realizo el cálculo de fragmentación según lo prescrito
free_space / (data_length + index_length)
Resulta que solo tengo una fragmentación del 0.2%. En mi humilde opinión eso es bastante poco realista.
Entonces las grandes preguntas son:
- ¿Cómo verifico la fragmentación de un índice en particular en MySQL, no en la tabla como un todo?
- ¿OPTIMIZE TABLE realmente soluciona la fragmentación interna / externa de un índice como en SQL Server?
- Cuando optimizo una tabla en MySQL, ¿realmente reconstruye todos los índices en la tabla?
- ¿Es realista pensar que reducir el espacio físico de un índice (sin reconstruir el árbol en sí) se traduce en un mejor rendimiento?
fuente
Respuestas:
La fragmentación del índice está muy sobrevalorada. No te preocupes por eso.
InnoDB fusiona dos bloques adyacentes, algo vacíos, como el procesamiento natural.
Las acciones aleatorias en un BTree hacen que gravite naturalmente hacia un promedio del 69% completo. Claro, esto no es 100%, pero la sobrecarga de "arreglar" no vale la pena.
SHOW TABLE STATUS
le ofrece algunas métricas, pero son defectuosas: "Data_free" incluye cierto espacio "libre", pero no otro espacio "libre".Hay espacio no utilizado en cada bloque; bloques libres de 16 KB; "extensiones" libres (fragmentos de nMB); Filas MVCC esperando ser cosechadas; los nodos no foliares tienen su propia fragmentación; etc.
Percona y Oracle tienen diferentes formas de ver qué tan grande (número de bloques) es un índice. No creo que ninguno de ellos sea útil debido a la definición limitada de "gratis". Parece que los bloques (16 KB cada uno) se asignan en trozos (varios MB), lo que lleva a creer que hay todo tipo de fragmentación. En realidad, generalmente es solo la mayoría de uno de estos fragmentos de varios MB. Y
OPTIMIZE TABLE
no necesariamente recupera nada del espacio.Si SQL Server está utilizando BTrees, es mentira decir que "no hay fragmentación". Piense en lo que sucede en una "división de bloques". O piense en los gastos generales de la desfragmentación continua. De cualquier manera, pierdes.
Además, tenga en cuenta que una tabla y un índice son estructuras esencialmente idénticas:
Si es así
innodb_file_per_table = ON
, puede ver claramente la contracción (si la hubiera) después de OPTIMIZAR TABLA mirando el.ibd
tamaño del archivo. ParaOFF
, la información está enterradaibdata1
, peroSHOW TABLE STATUS
puede ser razonablemente precisa ya que todo el espacio "libre" pertenece a cada tabla. Bueno, excepto por los trozos preasignados.Puede notar que una tabla de archivo por tabla recientemente optimizada tiene exactamente 4M, 5M, 6M o 7M de Data_free. Una vez más, esta es la preasignación y el hecho de no darle los detalles minuciosos.
He trabajado con InnoDB durante más de una década; He trabajado con miles de tablas diferentes, grandes y pequeñas. Digo que solo una mesa en mil realmente necesita
OPTIMIZE TABLE
. Usarlo en otras mesas es un desperdicio.105 columnas es mucho, pero quizás no demasiadas.
¿Tiene 55 índices en una tabla? Eso es malo. Eso es 55 actualizaciones por
INSERT
. Discutamos eso más a fondo. Tenga en cuenta queINDEX(a)
es inútil si también lo tieneINDEX(a,b)
. YINDEX(flag)
es inútil debido a la baja cardinalidad. (PeroINDEX(flag, foo)
puede ser útil).P1: No hay una buena manera de verificar todas las formas de fragmentación en los datos o en los índices secundarios.
Q2, Q3:
OPTIMIZE TABLE
reconstruye la tabla porCREATEing
una nueva tabla yINSERTing
todas las filas, luegoRENAMEing
yDROPping
. La reintroducción de los datos en el orden PK asegura que los datos estén bien desfragmentados. Los índices son otra cuestión.P4: Podría
DROP
yreCREATE
cada índice para limpiarlo. Pero este es un proceso extremadamente lento. 5.6 tiene algunas aceleraciones, pero no sé si ayudan con la desfragmentación.También es posible
ALTER TABLE ... DISABLE KEYS
, entoncesENABLE
ellos. Esto puede hacer una reconstrucción más eficiente de todos los índices secundarios a la vez.fuente
Pasar.
Reconstruye completamente la tabla y sus índices.
Esa es la misma pregunta con la misma respuesta.
No es realista pensar que podría reducir el espacio sin reconstruir el árbol. Van juntos
fuente
SHOW TABLE STATUS LIKE 'mytable'
daría una pista en ladata free
columna. dev.mysql.com/doc/refman/5.6/en/show-table-status.html