Mantenimiento de índices MySQL


12

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:

  1. ¿Cómo verifico la fragmentación de un índice en particular en MySQL, no en la tabla como un todo?
  2. ¿OPTIMIZE TABLE realmente soluciona la fragmentación interna / externa de un índice como en SQL Server?
  3. Cuando optimizo una tabla en MySQL, ¿realmente reconstruye todos los índices en la tabla?
  4. ¿Es realista pensar que reducir el espacio físico de un índice (sin reconstruir el árbol en sí) se traduce en un mejor rendimiento?

la tabla de optimización sin duda limpia el índice agrupado en innodb

1
Es una gran pregunta, pero no una de programación. Se trasladará a donde pertenece:>

Respuestas:


6

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 TABLEno 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:

  • B + Tree, basado en algún índice
  • Los "datos" se basan en la CLAVE PRIMARIA; cada índice secundario es un árbol B + basado en su índice.
  • El nodo hoja de los "datos" contiene todas las columnas de la tabla.
  • El nodo hoja de un índice secundario contiene las columnas de ese índice secundario, más las columnas de la CLAVE PRIMARIA.

Si es así innodb_file_per_table = ON, puede ver claramente la contracción (si la hubiera) después de OPTIMIZAR TABLA mirando el .ibdtamaño del archivo. Para OFF, la información está enterrada ibdata1, pero SHOW TABLE STATUSpuede 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 que INDEX(a)es inútil si también lo tiene INDEX(a,b). Y INDEX(flag)es inútil debido a la baja cardinalidad. (Pero INDEX(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 TABLEreconstruye la tabla por CREATEinguna nueva tabla y INSERTingtodas las filas, luego RENAMEingy DROPping. 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 y reCREATEcada í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, entonces ENABLEellos. Esto puede hacer una reconstrucción más eficiente de todos los índices secundarios a la vez.


Rick, quise decir '105' campos, no archivos
Nicolas

1

¿Cómo verifico la fragmentación de un índice en particular en MySQL, no en la tabla como un todo?

Pasar.

¿OPTIMIZE TABLE realmente soluciona la fragmentación interna / externa de un índice como en SQL Server?

Reconstruye completamente la tabla y sus índices.

Cuando optimizo una tabla en MySQL, ¿realmente reconstruye todos los índices en la tabla?

Esa es la misma pregunta con la misma respuesta.

¿Es realista pensar que reducir el espacio físico de un índice (sin reconstruir el árbol en sí) se traduce en un mejor rendimiento?

No es realista pensar que podría reducir el espacio sin reconstruir el árbol. Van juntos


Para responder # 1: Aunque no es muy preciso, SHOW TABLE STATUS LIKE 'mytable'daría una pista en la data freecolumna. dev.mysql.com/doc/refman/5.6/en/show-table-status.html
Jehad Keriaki

Lo sé, pero todavía falta el espacio de un índice en particular
Nicolas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.