Estructura de datos de índice de conceptos básicos de MySQL (24)

1 ¿Por qué utilizar índices?

La consulta secuencial y los datos utilizan una estructura de árbol binario para realizar consultas, como se muestra en la figura:
Insertar descripción de la imagen aquí

2 Índices y sus ventajas y desventajas

2.1 Descripción general del índice

La definición oficial de índice de MySQL es: Índice (Índice) es una estructura de datos que ayuda a MySQL a obtener datos de manera eficiente .

**La esencia del índice:**El índice es una estructura de datos. Simplemente puede entenderlo como una "estructura de datos de búsqueda rápida ordenada" que satisface un algoritmo de búsqueda específico. Estas estructuras de datos apuntan a datos de alguna manera, de modo que se pueden implementar implementaciones basadas en estas estructuras de datos 高级查找算法.

2.2 Ventajas

(1) De manera similar a crear un índice bibliográfico en una biblioteca universitaria, mejora la eficiencia de la recuperación de datos y reduce el costo 数据库的IO成本. Esta es también la razón principal para crear un índice.

(2) Al crear un índice único, se puede garantizar cada fila de la tabla de la base de datos 数据的唯一性.

(3) En términos de lograr la integridad referencial de los datos, sí 加速表和表之间的连接. En otras palabras, al consultar conjuntamente tablas secundarias dependientes y tablas principales, se puede mejorar la velocidad de consulta.

(4) Cuando se utilizan cláusulas de agrupación y clasificación para la consulta de datos, 减少查询中分组和排序的时间el consumo de CPU se puede reducir significativamente.

2.3 Desventajas

(1) Crear y mantener índices requiere tiempo 耗费时间y, a medida que aumenta la cantidad de datos, el tiempo dedicado también aumentará.

(2) Los índices deben ocupar 磁盘空间. Además del espacio de datos ocupado por la tabla de datos, cada índice también ocupa una cierta cantidad de espacio físico 存储在磁盘上. Si hay una gran cantidad de índices, el archivo de índice puede alcanzar el tamaño máximo de archivo más rápido. que el archivo de datos.

(3) Aunque el índice mejora en gran medida la velocidad de consulta, al mismo tiempo lo hará 降低更新表的速度. Al agregar, eliminar y modificar datos en la tabla, el índice debe mantenerse dinámicamente, lo que reduce la velocidad de mantenimiento de los datos.

3 Deducción de índices en InnoDB

3.1 Buscar antes de indexar

SELECT [列名列表] FROM 表名 WHERE 列名 = xxx;

1. Buscar dentro de una página

Suponiendo que actualmente hay relativamente pocos registros en la tabla, todos los registros se pueden almacenar en una página. Al buscar registros, existen dos situaciones basadas en diferentes condiciones de búsqueda:

  • Utilice la clave principal como criterio de búsqueda
    • 二分法Puede ubicar rápidamente la ranura correspondiente en el directorio de la página y luego recorrer los registros en el grupo correspondiente de la ranura para encontrar rápidamente el registro especificado.
  • Utilice otras columnas como criterio de búsqueda
    • Debido a que no existe el llamado directorio de páginas para claves no primarias en la página de datos, no podemos ubicar rápidamente la ranura correspondiente mediante el método de dicotomía. En este caso, solo puede recorrer cada registro en la lista enlazada individualmente comenzando desde el registro más pequeño y luego comparar si cada registro cumple con las condiciones de búsqueda. Evidentemente, la eficacia de esta búsqueda es muy baja.

2. Busca entre muchas páginas

En la mayoría de los casos, hay muchos registros almacenados en nuestras tablas y se necesitan muchas páginas de datos para almacenar estos registros. La búsqueda de registros en muchas páginas se puede dividir en dos pasos:

  1. Navegue a la página donde se encuentra el registro.
  2. Busque el registro correspondiente en la página donde se encuentra.

En ausencia de un índice, ya sea que estemos buscando en función de la columna de clave principal o del valor de otras columnas, dado que no podemos ubicar rápidamente la página donde se encuentra el registro, solo podemos buscar hacia abajo y en cada página. de acuerdo 从第一个页con 双向链表nuestro El método de búsqueda anterior busca el registro especificado. Debido a que es necesario recorrer todas las páginas de datos, este método es obviamente el mejor 超级耗时.

3.2 Índice de diseño

mysql> CREATE TABLE index_demo(
    -> c1 INT,
    -> c2 INT,
    -> c3 CHAR(1),
    -> PRIMARY KEY(c1)
    -> ) ROW_FORMAT = Compact;

Esta tabla recién creada index_demotiene 2 columnas de tipo INT y 1 columna de tipo CHAR(1), y hemos especificado la columna c1 como clave principal. Esta tabla utiliza formato de fila Compactpara almacenar registros. Aquí simplificamos el diagrama de formato de fila de la tabla index_demo:
Insertar descripción de la imagen aquí

  • record_type: Un atributo de la información del encabezado del registro, que indica el tipo de registro, 0que indica registros ordinarios, 1que indica registros de entrada de directorio, 2que indica registros mínimos y 3que indica registros máximos.
  • next_record: Un atributo de la información del encabezado del registro, que indica el desplazamiento de dirección de la siguiente dirección en relación con este registro. Usamos flechas para indicar quién es el siguiente registro.
  • 各个列的值: Sólo index_demotres columnas registradas en la tabla son c1, c2y c3.
  • 其他信息: Toda la información excepto los 3 tipos de información anteriores, incluidos los valores de otras columnas ocultas y la información adicional registrada.

El efecto de eliminar temporalmente otros elementos de información del diagrama de formato de registro y colocarlos es el siguiente:
Insertar descripción de la imagen aquí
El diagrama de colocar algunos registros en la página es:
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Tenga en cuenta que los números de los datos recién asignados pueden no ser consecutivos. Solo establecen una relación de lista enlazada manteniendo los números de la página anterior y la página siguiente. Además, el valor máximo de clave principal del registro de usuario en la página 10 es 5, y hay un registro en la página 28 con un valor de clave principal de 4. Debido a que 5>4, esto no coincide con el valor de clave principal del usuario. registro en la siguiente página de datos. Debe ser mayor que el requisito del valor de clave principal del registro de usuario en la página anterior, por lo que al insertar el registro con el valor de clave principal 4, debe ir acompañado de un movimiento de registro, es decir, el registro con el valor de clave principal 5 se mueve a la página 28. Luego inserte el registro con el valor de clave principal 4 en la página 10. El diagrama esquemático de este proceso es el siguiente: Este proceso muestra que en el proceso de
Insertar descripción de la imagen aquí
agregar , eliminando y modificando los registros en la página, debemos realizar algunas operaciones como el movimiento de registros.Asegúrese siempre de que este estado sea siempre verdadero: el valor de la clave principal del registro de usuario en la siguiente página de datos debe ser mayor que el valor de la clave principal del registro de usuario en la página anterior. A este proceso lo llamamos división de páginas.

¿Por qué necesitamos recorrer todas las páginas de datos cuando encontramos algunos registros según una determinada condición de búsqueda? Debido a que no hay un patrón en los registros de cada página, no sabemos qué registros de las páginas coinciden con nuestras condiciones de búsqueda, por lo que tenemos que recorrer todas las páginas de datos en secuencia. Entonces, ¿qué debemos hacer si queremos localizar rápidamente las páginas de datos donde se encuentran los registros que necesitamos encontrar? Podemos crear un directorio para ubicar rápidamente la página de datos donde se encuentra el registro, para crear este directorio debemos completar lo siguiente:

  • El valor de la clave principal del registro de usuario en la siguiente página de datos debe ser mayor que el valor de la clave principal del registro de usuario en la página anterior.
  • Cree una entrada de directorio para todas las páginas.

Insertar descripción de la imagen aquí
Tomando la página 28 como ejemplo, corresponde a la entrada de directorio 2. Esta entrada de directorio contiene el número de página 28 y el valor mínimo de clave primaria 5 del registro de usuario en la página. Solo necesitamos almacenar varios elementos del directorio continuamente en la memoria física (por ejemplo, una matriz) para realizar la función de buscar rápidamente un registro según el valor de la clave principal. Por ejemplo: para encontrar un registro con un valor de clave principal de 20, el proceso de búsqueda específico se divide en dos pasos: 1. Primero, determine rápidamente a partir de la entrada del directorio según el método de dicotomía que el registro con un valor de clave principal de 20 está en la entrada 3 del directorio (porque 12 < 20 < 209 ), su página correspondiente es la página 9. 2. Luego ubique el registro específico en la página 9 de acuerdo con el método de búsqueda de registros en la página mencionada anteriormente.

En este punto, se completa el directorio simple para la página de datos. Este directorio tiene un alias llamado índice.

2. Esquema de índice en InnoDB

① Iteración 1: página del registro de entrada del directorio

Así es como colocamos los elementos del directorio que usamos anteriormente en la página de datos: Como puede
Insertar descripción de la imagen aquí
ver en la imagen, hemos asignado una nueva página numerada 30 para almacenar específicamente registros de elementos del directorio. Aquí nuevamente enfatizamos las diferencias目录项记录 con 用户记录los ordinarios :

  • 目录项记录El valor de record_typees 1, mientras que el valor 普通用户记录de record_typees 0.
  • Los registros de entrada del directorio tienen solo 主键值和页的编号dos columnas, mientras que las columnas de los registros de usuario normales las define el usuario y pueden incluir 很多列columnas ocultas agregadas por el propio InnoDB.
  • min_rec_maskComprenda: también hay un atributo llamado en la información del encabezado del registro , solo el valor 目录项记录de clave primaria 目录项记录más pequeño en la página almacenada, y los valores de otros registros son todos .min_rec_mask1min_rec_mask0

Similitud : ambos usan la misma página de datos y ambos generarán el valor de la clave principal (directorio de páginas), que se puede usar para acelerar la consulta Page Directoryal buscar según el valor de la clave principal .二分法

20Ahora, tomando como ejemplo la búsqueda de un registro con una clave principal, los pasos para encontrar un registro basado en un determinado valor de clave principal se pueden dividir aproximadamente en los dos pasos siguientes:

  1. Vaya primero a la página almacenada 目录项记录, es decir, la página 30 y 二分法ubique rápidamente la entrada del directorio correspondiente. Debido a que 12 <20 <209, la página donde se encuentra el registro correspondiente es la página 9.

  2. Luego vaya a la página 9 donde se almacenan los registros de usuario y 二分法localice rápidamente el registro de usuario con el valor de clave principal 20.

② Iteración 2 veces: páginas para múltiples registros de entrada de directorio. Como
Insertar descripción de la imagen aquí
puede verse en la figura, necesitamos dos nuevas páginas de datos después de insertar un registro de usuario con un valor de clave principal de 320:

  • Recién generado para almacenar este registro de usuario 页31.
  • Debido a que los registros de entrada del directorio se almacenaron originalmente 页30的容量已满(anteriormente asumimos que solo se podían almacenar 4 registros de entrada del directorio), se tuvo que usar uno nuevo para 页32almacenar 页31las entradas del directorio correspondientes.

Ahora, debido a que hay más de una página que almacena registros de entradas de directorio, si queremos encontrar un registro de usuario basado en el valor de la clave principal, se necesitan aproximadamente 3 pasos. Tomando el registro con el valor de la clave principal como ejemplo 20:

  1. Se determina 目录项记录页que actualmente tenemos dos páginas que almacenan registros de entradas de directorio, a saber 页30y 页32, y debido a que el rango del valor de clave principal de la entrada de directorio representada por la página 30 es [1, 320), el valor de clave principal de la entrada de directorio representado por la página 32 no es menor que 320, por lo que 20la entrada del directorio correspondiente al registro con el valor de la clave principal se registra en 页30.

  2. Registre páginas a través de entradas de directorio 确定用户记录真实所在的页. 目录项记录Se ha descrito el método para localizar un registro de entrada de directorio en una página almacenada por su valor de clave principal.

  3. Localice el registro específico en la página donde realmente se almacena el registro de usuario.

③ Iterar 3 veces: página de directorio de página de registro de elementos de directorio
Insertar descripción de la imagen aquí

Como se muestra en la figura, hemos generado un almacenamiento para elementos del directorio de nivel superior 页33. Los dos registros en esta página representan la página 30 y la página 32 respectivamente. Si el valor de la clave principal del registro de usuario está entre [1, 320), vaya a la página 30 para busque un directorio más detallado. Si el registro de entrada tiene un valor de clave principal 不小于320, vaya a la página 32 para encontrar registros de entrada de directorio más detallados.

Podemos usar el siguiente diagrama para describirlo:
Insertar descripción de la imagen aquí
Esta estructura de datos, su nombre es B+树.

B+árbol

Un nodo de árbol B+ en realidad se puede dividir en muchas capas. La capa más baja, que es la capa donde se almacenan nuestros registros de usuario, se designa como la primera 0capa y luego las capas se agregan hacia arriba. Antes hicimos una suposición muy extrema: la página que almacena registros de usuarios 最多存放3条记录y la página que almacena registros de entradas de directorio 最多存放4条记录. De hecho, la cantidad de registros almacenados en una página en un entorno real es muy grande. Suponga que todas las páginas de datos representadas por nodos hoja que almacenan registros de usuario se pueden almacenar, y todas las páginas de datos representadas por nodos internos que almacenan registros de entrada de directorio se pueden almacenar 100条用户记录. ser almacenado 1000条目录项记录, entonces:

  • Si el árbol B+ tiene solo un nivel, es decir, solo se usa un nodo para almacenar registros de usuario, puede almacenar hasta 1001 registro.
  • Si el árbol B+ tiene 2 niveles, puede almacenar hasta 1000×100=10,00001 registro.
  • Si el árbol B+ tiene 3 niveles, puede almacenar hasta 1000×1000×100=1,0000,00001 registro.
  • Si el árbol B+ tiene 4 niveles, puede almacenar hasta 1000×1000×1000×100=1000,0000,00001 registro. ¡Todo un récord! ! !

100000000000¿Puedes almacenar registros en tu tabla ? Entonces, en circunstancias normales, 用到的B+树都不会超过4层cuando usamos el valor de la clave principal para encontrar un registro, solo necesitamos buscar dentro de 4 páginas como máximo (buscar 3 páginas de entrada de directorio y una página de registro de usuario), y debido a que existen las llamadas (página directorio), para que también pueda localizar rápidamente registros Page Directorydentro de la página .二分法

3.3 Conceptos comunes de índices

1. Índice agrupado

Características:

  1. Usar el tamaño del valor de la clave principal del registro para ordenar registros y páginas tiene tres implicaciones:

    • 页内Los registros están ordenados según el tamaño de la clave primaria 单向链表.

    • Cada almacenamiento 用户记录的页también se organiza en orden según el tamaño de la clave principal del registro de usuario en la página 双向链表.

    • El almacenamiento 目录项记录的页se divide en diferentes niveles y las páginas del mismo nivel también se organizan en orden de acuerdo con el tamaño de la clave principal del registro de entrada del directorio en la página 双向链表.

  2. El árbol B+ 叶子节点almacena registros de usuario completos.

    El llamado registro de usuario completo significa que los valores de todas las columnas (incluidas las columnas ocultas) se almacenan en este registro.

ventaja:

  • 数据访问更快, debido a que un índice agrupado almacena el índice y los datos en el mismo árbol B+, recuperar datos de un índice agrupado es más rápido que un índice no agrupado.
  • Los índices agrupados son muy rápidos para 排序查找sumas de claves primarias范围查找
  • De acuerdo con el orden de disposición del índice agrupado, cuando la consulta muestra un cierto rango de datos, debido a que los datos están estrechamente conectados, la base de datos no necesita extraer datos de múltiples bloques de datos 节省了大量的io操作.

defecto:

  • 插入速度严重依赖于插入顺序, insertar en el orden de las claves principales es la forma más rápida; de lo contrario, se producirán divisiones de páginas, lo que afectará gravemente el rendimiento. Por lo tanto, para las tablas InnoDB, generalmente definimos una columna de ID de incremento automático como clave principal.
  • 更新主键的代价很高, porque hará que la fila actualizada se mueva. Por lo tanto, para las tablas InnoDB, generalmente definimos la clave principal como no actualizable.
  • 二级索引访问需要两次索引查找, busque el valor de la clave principal por primera vez y busque los datos de la fila según el valor de la clave principal por segunda vez

límite:

  • Para la base de datos MySql, actualmente solo el motor de datos InnoDB admite índices agrupados, mientras que MyISAM no admite índices agrupados.
  • Dado que solo puede haber un método de clasificación de almacenamiento físico para los datos, cada tabla MySql solo puede tener un índice agrupado, que suele ser la clave principal de la tabla.
  • Si no hay una clave principal definida, Innodb elegirá un índice único no vacío. Si no existe tal índice, Innodb definirá implícitamente una clave primaria como un índice agrupado.
  • Para aprovechar al máximo las características de agrupación del índice agrupado, la columna de clave principal de la tabla Innodb debe intentar utilizar ID secuenciales ordenados. No se recomienda utilizar ID desordenados, como UUID, MD5, Hash y cadenas. columnas como claves primarias, lo que no puede garantizar la integridad de los datos.crecimiento secuencial.

2. Índice secundario (índice auxiliar, índice no agrupado)

El índice agrupado solo puede funcionar cuando la condición de búsqueda es el valor de la clave principal, porque los datos en el árbol B+ se ordenan según la clave principal.

¿Y qué pasa si queremos utilizar otras columnas como criterio de búsqueda? Ciertamente no puede ser un recorrido único de registros de principio a fin.

Respuesta: Podemos construir varios árboles B+ más y los datos en diferentes árboles B+ adoptan diferentes reglas de clasificación. Por ejemplo, usamos el tamaño de la columna C2 como página de datos y regla de clasificación para los registros en la página, y luego construimos un árbol B+, como se muestra en la figura (la siguiente figura no es completamente correcta, de hecho, la La página del directorio también contiene el valor de la clave principal):
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
este árbol B+ es diferente del índice agrupado presentado anteriormente en varios aspectos:

  • Usar el tamaño de la columna del registro c2 para ordenar registros y páginas tiene tres implicaciones:
    • Los registros de la página están organizados en una lista enlazada unidireccional según el tamaño de la columna c2.
    • Cada página que almacena registros de usuarios también está organizada en una lista doblemente vinculada según el tamaño de la columna c2 registrada en la página.
    • Las páginas que almacenan registros de entradas de directorio se dividen en diferentes niveles. Las páginas del mismo nivel también se organizan en una lista doblemente vinculada según el tamaño de la columna c2 de los registros de entradas de directorio en la página.
  • Los nodos hoja del árbol B+ no almacenan el registro de usuario completo, sino solo los valores de la columna c2 + la clave principal.
  • El registro de entrada del directorio ya no es una combinación de clave principal + número de página, sino una combinación de columna c2 + número de página.

Concepto: Volviendo a la tabla , solo podemos determinar el valor de la clave principal del registro que queremos encontrar en función de este árbol B+ ordenado por el tamaño de la columna c2, por lo que si queremos encontrar el registro de usuario completo en función del valor de columna c2, todavía tenemos que ir al índice agrupado Compruébelo nuevamente, este proceso se llama retorno de tabla. Es decir, consultar un registro de usuario completo según el valor de la columna c2 requiere el uso de 2 árboles B+.

Debido a que este árbol B+ construido en base a columnas de clave no primaria requiere una operación de retorno de tabla para ubicar el registro de usuario completo, esta hoja B+ se denomina índice secundario o índice auxiliar . Dado que utilizamos el tamaño de la columna c2 como regla de clasificación del árbol B+, también llamamos a este árbol B+ índice creado para la columna c2.

La existencia de un índice no agrupado no afecta la organización de los datos en el índice agrupado, por lo que una tabla puede tener varios índices no agrupados.

Resumen : Los principios de los índices agrupados y los índices no agrupados son diferentes y también existen algunas diferencias en su uso:

Los nodos hoja del índice agrupado almacenan nuestros registros de datos y los nodos hoja del índice no agrupado almacenan la ubicación de los datos. Los índices no agrupados no afectan el orden de almacenamiento físico de las tablas de datos.
Una tabla solo puede tener un índice agrupado, porque solo puede haber un método de clasificación y almacenamiento, pero puede tener múltiples índices no agrupados, es decir, múltiples directorios de índice proporcionan recuperación de datos.
Cuando se utiliza un índice agrupado, la eficiencia de la consulta de datos es alta , pero si los datos se insertan, eliminan, actualizan, etc., la eficiencia será menor que la de un índice no agrupado.
Pregunta: ¿Por qué necesitamos otra operación de retorno de tabla? ¿No está bien colocar el registro de usuario completo directamente en el nodo hoja?

Si coloca los registros de usuario completos en los nodos hoja, no necesita devolver la tabla, pero ocupa demasiado espacio, lo que equivale a copiar todos los registros de usuario cada vez que crea un árbol B +, que es un Un poco de desperdicio de espacio de almacenamiento.

3. Para el índice conjunto,
también podemos usar el tamaño de varias columnas como regla de clasificación al mismo tiempo, es decir, crear índices para varias columnas al mismo tiempo. Por ejemplo, queremos que el árbol B + se ordene según al tamaño de las columnas c2 y c3. Esto contiene dos niveles de significado:

  • Primero ordene los registros y las páginas según la columna c2.
  • Cuando la columna c2 de los registros es la misma, la columna c3 se utiliza para ordenar.

Tenga en cuenta que el árbol B+ establecido con el tamaño de las columnas c2 y c3 como regla de clasificación se denomina índice conjunto, que es esencialmente un índice secundario. Su significado es diferente a la expresión de establecer índices para las columnas c2 y c3 respectivamente, las diferencias son las siguientes:

  • La creación de un índice conjunto solo creará un árbol B+ como se muestra arriba.
  • La creación de índices para las columnas c2 y c3 creará dos árboles B+ según el tamaño de las columnas c2 y c3 respectivamente.

Insertar descripción de la imagen aquí

3.4 Cosas a tener en cuenta sobre el índice de árbol B+ de InnoDB

1. La ubicación de la página raíz permanece sin cambios durante miles de años.

Cuando presentamos el índice B + anteriormente, para facilitar la comprensión de todos, primero dibujamos todos los nodos hoja que almacenan registros de usuario y luego dibujamos los nodos internos que almacenan registros de entrada de directorio. De hecho, el proceso de formación del árbol B + es como sigue:

  • Siempre que se crea un índice de árbol B+ para una determinada tabla (el índice agrupado no se crea artificialmente, está ahí de forma predeterminada), se creará una página para este índice 根节点. 根节点Cuando no hay datos en la tabla al principio, no hay registros de usuario ni registros de entrada de directorio en cada índice del árbol B+ .
  • Al insertar posteriormente registros de usuario en la tabla, los registros de usuario se almacenan primero en este archivo 根节点.
  • Cuando se continúan insertando los registros disponibles en el nodo raíz 空间用完时, todos los registros en el nodo raíz se copiarán a una página recién asignada, como 页a, y luego 页分裂la operación en esta nueva página dará como resultado otra página nueva, como 页b. 页aEn este momento, el registro recién insertado se asignará según el tamaño del valor de la clave (es decir, el valor de la clave principal en el índice agrupado, el valor de la columna de índice correspondiente en el índice secundario) y luego se actualizará. para almacenar 页bregistros de entradas de directorio 根节点... de páginas.

Se debe prestar especial atención a este proceso: el nodo raíz de un índice de árbol B+ no se moverá desde la fecha de nacimiento. De esta manera, siempre que creemos un índice en una tabla determinada, el número de página de su nodo raíz se registrará en algún lugar y luego, InnoDBcuando el motor de almacenamiento necesite usar este índice, eliminará el nodo raíz de ese índice fijo. lugar Número de página para acceder a este índice.

2. Unicidad de los registros de entrada de directorio en nodos internos.

Sabemos que el contenido de los registros de entrada del directorio en los nodos internos del índice del árbol B+ es 索引列+页号una buena coincidencia, pero esta coincidencia es un poco vaga para el índice secundario. Tomemos index_demouna tabla como ejemplo. Supongamos que los datos de esta tabla se ven así:

c1 c2 c3
1 1 'tú'
3 1 'd'
5 1 'tú'
7 1 'a'

Si el contenido de las entradas del directorio en el índice secundario es solo 索引号+页号una coincidencia, entonces c2el árbol B+ después de indexar la columna debería verse así:
Insertar descripción de la imagen aquí
Si queremos insertar una nueva fila de registros, los valores de c1, c2 , y c3 son 9, 1, 'c', entonces nos encontramos con un gran problema al modificar el árbol B+ correspondiente al índice secundario establecido para la columna c2: Dado que el registro de entrada del directorio almacenado en la página 3 está compuesto por el valor de la columna c2 + número de página, página 3 El valor de la columna c2 correspondiente a los dos registros de entrada del directorio es 1, y el valor de la columna c2 de nuestro registro recién insertado también es 1, por lo que nuestro registro recién insertado debe colocarse en la página 4, o ¿Debería colocarse en la página 5? La respuesta es: no estoy seguro.

Para que el registro recién insertado encuentre en qué página se encuentra, debemos asegurarnos de que el registro de entrada del directorio del nodo en la misma capa del árbol B+ sea único, excepto el campo de número de página. Por lo tanto, el contenido del registro de entrada del directorio del nodo interno del índice secundario en realidad se compone de tres partes:

  • valor de la columna de índice
  • valor de clave primaria
  • Número de página

Es decir, también agregamos el valor de la clave principal al registro de entrada del directorio en el nodo del índice secundario, lo que puede garantizar que cada registro de entrada del directorio en cada nodo del árbol B+ sea único, excepto el campo de número de página, por lo que El diagrama después de crear un índice secundario para la columna c2 debería verse así:
Insertar descripción de la imagen aquí
Cuando insertamos el registro (9,1,'c'), debido a que el registro de entrada del directorio almacenado en la página 3 se compone de la columna c2 + clave primaria + la valor del número de página. Primero puede comparar el valor de la columna c2 del nuevo registro con el valor de c2 de cada registro de entrada de directorio en la página 3. Si los valores de la columna c2 son los mismos, puede comparar el valor de clave primaria, porque B+ El valor de la columna c2 + clave primaria de diferentes registros de entrada de directorio en el mismo nivel del árbol debe ser diferente, por lo que el único registro de entrada de directorio debe ubicarse al final. En este caso, finalmente es determinó que el nuevo registro debe insertarse en la página 5.

3. Una página puede almacenar al menos 2 registros.

Un árbol B+ puede almacenar fácilmente cientos de millones de registros con solo unos pocos niveles, ¡y la velocidad de consulta es bastante buena! Esto se debe a que el árbol B+ es esencialmente un directorio grande de varios niveles. Cada vez que pasa por un directorio, se filtrarán muchos subdirectorios no válidos hasta que el último directorio al que se acceda almacene los datos reales. Entonces, ¿cuál será el efecto si sólo se almacena un subdirectorio en un directorio grande? Es decir, hay muchísimos niveles de directorio, y en el último directorio se almacena un registro que almacena datos reales. Después de pasar mucho tiempo, ¿solo se puede almacenar un registro de usuario real? entoncesInnoDB的一个数据页至少可以存放两条记录

4. Esquema de índice en MyISAM

4.1 Principio del índice MyISAM

Los motores de almacenamiento aplicables para índices de árbol B se muestran en la tabla:

Motor de índice/almacenamiento MiISAM InnoDB Memoria
Índice de árbol B apoyo apoyo apoyo

Incluso si varios motores de almacenamiento admiten el mismo tipo de índice, sus principios de implementación también son diferentes. El índice predeterminado de Innodb y MyISAM es el índice Btree, mientras que el índice predeterminado de Memory es el índice Hash.

El motor MyISAM lo utiliza B+Treecomo estructura de índice y almacena el campo de datos del nodo hoja 数据记录的地址.
Insertar descripción de la imagen aquí
Si creamos un índice secundario en Col2, la estructura de este índice se muestra a continuación:
Insertar descripción de la imagen aquí

4.2 Comparación entre MyISAM e InnoDB

Todos los métodos de indexación de MyISAM son "no agrupados", lo cual es diferente de InnoDB, que contiene un índice agrupado.

Resumen de las diferencias entre índices en los dos motores:

① En el motor de almacenamiento InnoDB, solo necesitamos 聚簇索引realizar una búsqueda basada en el par de valores de clave primaria para encontrar el registro correspondiente, pero en MyISAMInnoDB, necesitamos realizar una 回表operación, lo que significa que el índice establecido en MyISAM es equivalente a todos 二级索引.

② El archivo de datos de InnoDB en sí es un archivo de índice, mientras que el archivo de índice MyISAM y el archivo de datos son 分离的.El archivo de índice solo guarda la dirección del registro de datos.

③ El dominio de datos de índice no agrupado de InnoDB almacena los registros correspondientes 主键的值, mientras que los registros de índice MyISAM 地址. En otras palabras, todos los índices no agrupados en InnoDB hacen referencia a la clave principal como campo de datos.

④ La operación de retorno de tabla de MyISAM es muy 快速simple, porque toma el desplazamiento de dirección para obtener datos directamente del archivo. Por otro lado, InnoDB obtiene la clave principal y luego busca el registro en el índice agrupado. Aunque no es lento, todavía no es tan bueno como acceder directamente usando la dirección.

⑤ Tabla de requisitos de InnoDB 必须有主键( MyISAM可以没有). Si no se especifica explícitamente, el sistema MySQL seleccionará automáticamente una columna que no puede ser nula e identificará de forma única el registro de datos como clave principal. Si dicha columna no existe, MySQL genera automáticamente un campo implícito como clave principal para la tabla InnoDB. Este campo tiene 6 bytes de longitud y es de tipo entero largo.

4 El costo de la indexación

El índice es algo bueno, pero no se puede crear al azar, consumirá espacio y tiempo:

  • costo del espacio

Cada vez que se crea un índice, se debe construir un árbol B+ para él. Cada nodo de cada árbol B+ es una página de datos. Una página ocupará el espacio de almacenamiento de forma predeterminada. Un árbol B+ grande se compone de muchas páginas de datos. , 16KBeso Es un gran espacio de almacenamiento.

  • costo de tiempo

Cada vez que opera con los datos de la tabla 增、删、改, debe modificar cada índice del árbol B+. 从小到大的顺序排序Y hemos dicho que los nodos de cada nivel del árbol B+ se componen según el valor de la columna de índice 双向链表. Ya sean registros en los nodos hoja o registros en los nodos internos (es decir, ya sean registros de usuario o registros de entrada de directorio), forman una lista vinculada unidireccional en orden de menor a mayor en el valor de la columna de índice. . Las operaciones de adición, eliminación y modificación pueden dañar la clasificación de nodos y registros, por lo que el motor de almacenamiento necesita tiempo adicional para realizar algunas operaciones 记录移位, y otras operaciones para mantener la clasificación de nodos y registros. Si construimos muchos índices, el árbol B+ correspondiente a cada índice deberá someterse a operaciones de mantenimiento relacionadas, lo que obstaculizará el rendimiento.页面分裂页面回收

5 Razonabilidad de la selección de la estructura de datos MySQL

5.1 Árbol de búsqueda binaria

Si utilizamos un árbol binario como estructura de índice, el número de IO del disco está relacionado con la altura del árbol de índice. Por ejemplo, el árbol de búsqueda binaria que creamos para la secuencia (34,22,89,5,23,77,91) se muestra en la siguiente figura:
Insertar descripción de la imagen aquí
Pero hay situaciones especiales, es decir, a veces la profundidad del binario El árbol es muy grande. Por ejemplo, la secuencia de datos que damos es (5,22,23,34,77,89,91); luego el árbol de búsqueda binario creado es como se muestra en la siguiente figura: El
Insertar descripción de la imagen aquí
segundo árbol de arriba también es un árbol de búsqueda binario. pero el rendimiento ha degenerado en una lista vinculada y la complejidad temporal de la búsqueda de datos se ha convertido en O (n). Puede ver que la profundidad del primer árbol es 3, lo que significa que solo se necesitan 3 comparaciones como máximo para encontrar el nodo La profundidad del segundo árbol es 7, y se necesitan hasta 7 comparaciones para encontrar el nodo.

Para mejorar la eficiencia de las consultas, es necesario reducir la cantidad de E/S de disco. Para reducir la cantidad de E/S de disco, es necesario reducir la altura del árbol tanto como sea posible. La estructura del árbol original "delgada y alta" debe cambiarse a "corta y gruesa". Cuantas más bifurcaciones haya en cada nivel del árbol, mejor.

5.2 árbol AVL

Para resolver el problema anterior del árbol de búsqueda binario que degenera en una lista enlazada, se ha propuesto un árbol de búsqueda binario equilibrado, también conocido como árbol AVL, que agrega restricciones sobre la base del árbol de búsqueda binario y tiene las siguientes propiedades :

Es un árbol vacío o el valor absoluto de la diferencia de altura entre sus subárboles izquierdo y derecho no excede 1, y tanto el subárbol izquierdo como el derecho son árboles binarios equilibrados.

El tiempo de consulta de datos depende principalmente del número de E/S del disco. Si adoptamos la forma de árbol binario, incluso si se mejora mediante un árbol de búsqueda binario equilibrado, la profundidad del árbol es O(log2n). Cuando n es relativamente grande, la profundidad también es relativamente pequeña y alta, como se muestra a continuación:

Insertar descripción de la imagen aquí
Cada vez que se accede a un nodo, se requiere una operación de E/S de disco. Para el árbol anterior, necesitamos realizar 5 operaciones de E/S. Aunque la eficiencia de un árbol binario equilibrado es alta, la profundidad del árbol también es alta, lo que significa que la cantidad de operaciones de E/S del disco es alta, lo que afectará la eficiencia de la consulta de datos general.

Para los mismos datos, ¿qué pasa si cambiamos el árbol binario a un árbol M-ario (M>2)? Cuando M = 3, el siguiente árbol ternario puede almacenar los mismos 31 nodos:
Insertar descripción de la imagen aquí
En este momento vemos que la altura del árbol se reduce. Cuando la cantidad de datos N es grande y el árbol de bifurcación M del árbol es grande Cuando , la altura del árbol M-ario será mucho menor que la altura del árbol binario (M>2). Por lo tanto, necesitamos cambiar el árbol de "flaco y alto" a "bajo y gordo".

5.3 Árbol B

El nombre en inglés de B-tree es Balance Tree, que es un árbol de búsqueda equilibrado de múltiples vías, abreviado como B-Tree. Su altura es mucho menor que la altura de un árbol binario equilibrado.
Insertar descripción de la imagen aquí
Un árbol B de orden M (M>2) tiene las siguientes características:

  1. El rango del número de hijos del nodo raíz es [2,M].

  2. Cada nodo intermedio contiene k-1 palabras clave y k hijos. El número de hijos = el número de palabras clave + 1. El rango de valores de k es [ceil(M/2), M].

  3. Los nodos hoja incluyen palabras clave k-1 (los nodos hoja no tienen hijos) y el rango de valores de k es [ceil(M/2), M].

  4. Supongamos que las claves de los nodos del nodo intermedio son: Clave [1], Clave [2], ..., Clave [k-1], y las claves están ordenadas en orden ascendente, es decir, Clave [i] <Clave [yo+1]. En este momento, las palabras clave k-1 equivalen a dividir k rangos, es decir, correspondientes a k punteros, a saber: P [1], P [2], ..., P [k], donde P [1] apunta a La clave es más pequeña que el subárbol de Clave [1], P [i] apunta al subárbol al que pertenece la clave (Clave [i-1], Clave [i]) y P [k] apunta al subárbol donde la clave es mayor que el subárbol clave[k-1].

  5. Todos los nodos de las hojas están en el mismo nivel.

El árbol B representado en la imagen de arriba es un árbol B de tercer orden. Podemos mirar el bloque de disco 2. La clave dentro es (8, 12). Tiene 3 hijos (3, 5), (9, 10) y (13, 15). Puedes ver que (3, 5) es menor. que 8, (9, 10) está entre 8 y 12, y (13, 15) es mayor que 12, lo que se ajusta perfectamente a las características que acabamos de dar.

Luego veamos cómo usar B-tree para buscar. Suponiendo que lo queramos 查找的关键字是 9, los pasos se pueden dividir en los siguientes pasos:

  1. Lo comparamos con la clave del nodo raíz (17, 35), si 9 es menor que 17, obtenemos el puntero P1;

  2. Encuentre el bloque de disco 2 según el puntero P1, la clave es (8, 12), debido a que 9 está entre 8 y 12, obtenemos el puntero P2;

  3. Busque el bloque de disco 6 según el puntero P2, la clave es (9, 10) y luego encontramos la clave 9.

Puede ver que durante el proceso de búsqueda del árbol B, hacemos muchas comparaciones, pero si los datos se leen y comparan en la memoria, este tiempo es insignificante. La lectura del bloque de disco en sí requiere operaciones de E/S, lo que consume más tiempo que la comparación en la memoria y es un factor importante en el tiempo de búsqueda de datos. B 树相比于平衡二叉树来说磁盘 I/O 操作要少, que es más eficiente que un árbol binario equilibrado en la consulta de datos. Entonces._ 只要树的高度足够低,IO次数足够少,就可以提高查询性能_

5.4 Árbol B+

La diferencia entre el árbol B+ y el árbol B :

  1. Un nodo con k hijos tiene k palabras clave. Es decir, el número de hijos = el número de palabras clave, y en el árbol B, el número de hijos = el número de palabras clave + 1.

  2. Las palabras clave de nodos que no son hoja también existirán en los nodos secundarios y son el máximo (o mínimo) de todas las palabras clave en los nodos secundarios.

  3. Los nodos que no son hoja solo se utilizan para indexar y no guardan registros de datos. La información relacionada con los registros se coloca en los nodos hoja. Y en el árbol B 非叶子节点既保存索引,也保存数据记录,.

  4. Todas las palabras clave aparecen en nodos hoja, que forman una lista enlazada ordenada, y los propios nodos hoja están vinculados en orden de pequeño a grande según el tamaño de las palabras clave.

Tanto el árbol B como el árbol B+ se pueden utilizar como estructuras de datos de índice. En MySQL se utiliza el árbol B+.

Sin embargo, el árbol B y el árbol B + tienen cada uno sus propios escenarios de aplicación. No se puede decir que el árbol B + sea completamente mejor que el árbol B, o viceversa.

Pregunta para pensar: para reducir IO, ¿se cargará el árbol de índice de inmediato?

1. El índice de la base de datos se almacena en el disco. Si la cantidad de datos es grande, el tamaño del índice inevitablemente será grande, excediendo varios G.

2. Cuando utilizamos la consulta de índice, es imposible cargar todos los índices G en la memoria. Todo lo que podemos hacer es: cargar cada página del disco una por una, porque la página del disco corresponde al nodo del árbol de índice.

Pregunta: ¿Cuál es la capacidad de almacenamiento del árbol B+? ¿Por qué se dice que, en general, la búsqueda de registros de fila solo requiere de 1 a 3 E/S de disco como máximo?

El tamaño de la página en el motor de almacenamiento InnoDB es de 16 KB. El tipo de clave principal de una tabla general es INT (ocupa 4 bytes) o BIGINT (ocupa 8 bytes). El tipo de puntero es generalmente de 4 u 8 bytes, lo que significa una página ( un nodo en B+Tree) almacena aproximadamente 16KB/(8B+8B)=1K valores clave. Debido a que es una estimación, el valor de K aquí es 10 3 para facilitar el cálculo . En otras palabras, un índice B+Tree con una profundidad de 3 puede mantener 10 3 * 10^3 * 10^3 = mil millones de registros. (Aquí se supone que una página de datos también almacena datos de registros de 10^3 filas)

En situaciones reales, es posible que cada nodo no esté completamente lleno, por lo que en la base de datos B+Tree的高度一般都在2~4层. El motor de almacenamiento InnoDB de MySQL está diseñado con el nodo raíz residente en la memoria, lo que significa que solo se necesitan de 1 a 3 operaciones de E/S de disco para encontrar registros de fila para un determinado valor clave.

Pregunta: ¿Por qué el árbol B+ es más adecuado que el árbol B para la indexación de archivos y la indexación de bases de datos de sistemas operativos en aplicaciones prácticas?

1. Los costos de lectura y escritura del disco del árbol B+ son menores

Los nodos internos del árbol B+ no tienen punteros a información específica sobre las palabras clave. Por lo tanto, sus nodos internos son más pequeños que los del árbol B. Si todas las palabras clave del mismo nodo interno se almacenan en el mismo bloque de disco, más palabras clave puede contener el bloque de disco. Cuantas más palabras clave deban buscarse se leen en la memoria a la vez. En términos relativos, se reduce el número de lecturas y escrituras de IO.

2. La eficiencia de las consultas del árbol B+ es más estable

Porque el punto no terminal no es el nodo que finalmente apunta al contenido del archivo, sino que es solo el índice de la palabra clave en el nodo hoja. Todas las búsquedas de cualquier palabra clave deben tomar una ruta desde el nodo raíz hasta el nodo hoja. La longitud de la ruta de todas las consultas de palabras clave es la misma, lo que da como resultado la misma eficiencia de consulta para cada dato.

Pregunta para pensar: la diferencia entre el índice Hash y el índice de árbol B+

1. Índice hash 不能进行范围查询, pero el árbol B+ sí. Esto se debe a que los datos señalados por el índice Hash no están ordenados, mientras que los nodos hoja del árbol B+ son una lista enlazada ordenada.

2. Índice hash 不支持联合索引的最左侧原则(es decir, parte del índice conjunto no se puede utilizar), pero el árbol B+ sí. Para los índices conjuntos, el índice Hash fusiona las claves de índice y luego calcula el valor Hash juntos al calcular el valor Hash, por lo que el valor Hash no se calcula por separado para cada índice. Por lo tanto, si se utilizan uno o varios índices del índice conjunto, no se puede utilizar el índice conjunto.

3. Índice Hash 不支持 ORDER BY 排序, debido a que los datos señalados por el índice Hash están desordenados, no puede desempeñar un papel en la optimización de clasificación, mientras que los datos del índice del árbol B + están ordenados y pueden desempeñar un papel en la optimización de clasificación ORDER BY del campo. De la misma manera, no podemos usar el índice Hash 模糊查询. Cuando el árbol B + usa LIKE para consultas difusas, las consultas difusas después de LIKE (como el porcentaje final) pueden desempeñar un papel de optimización.

4 、InnoDB不支持哈希索引

Supongo que te gusta

Origin blog.csdn.net/zhufei463738313/article/details/130582286
Recomendado
Clasificación