(1) Estructura de datos de optimización del índice MySql y optimización del rendimiento

El índice es una estructura de datos ordenada que ayuda a Mysql a obtener datos de manera eficiente

¿Qué es el índice?


 1. 官方介绍索引是帮助Mysql高效获取数据的数据结构,更通俗的说,数据库索引好比是一本书前面的目录能加快数据库的查询速度
 2. 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中的(可能存储在单独的索引文件中,也可能和数据一起存储在数据文件中)
 3. 我们通常所说的索引,包括聚集索引,覆盖索引,组合索引,前缀索引,唯一索引等没有特别说明,默认都是使用B+树结构组织(多路搜索树,并不一定是二叉的)索引
 
 索引的优势和劣势
 优势:
 
 1. 可以提高数据检索的效率,降低数据库的IO成本类似于书的目录
 2. 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
 	被索引的列会自动进行排序,包括【单列索引】和【组合索引】只是组合索引的排序要复杂一些
 	如果按照索引列的顺序进行排序,对应order by 语句来说,效率就会提高很多
 劣势:
 1. 索引会占用磁盘空间
 2.索引虽然会提高查询效率,但是会降低更新表的效率。比如每次对表进行增删改操作Mysql不仅要保存数据,还有保存
 或者更新对应的索引文件

1. Estructura de datos e implementación de índices

- 二叉树(右边的元素大于去父元素,左边的元素小于其父元素)
- 红黑树  (是一种自平衡二叉查找树)
- Hash表 (Hash表再等值查询时,效率很高,时间复杂度为O(1) 但是不支持范围快速查找,范围查找时还是只能通过扫描全表来实现)
- B-Tree (叶节点具有相同的深度,叶节点的指针为空 所有索引元素不重复 节点中的数据索引从左到右递增排列)
- B+Trees (多叉平衡树  非椰子节点不存储Data,只存储索引(冗余),可以放更多的索引,叶子节点包含所有索引字段 叶子节点用指针连接,提高区间访问的性能)

MOSTRAR ESTADO GLOBAL COMO 'Innodb_page_size';
B + Los árboles con una altura de árbol de 3 pueden almacenar aproximadamente 21,902,400 índices

  • 1. Índice agrupado: [Índice agrupado]: el índice y los datos se juntan (los nodos hoja contienen datos completos)
  • 2. Índice no agrupado- [Índice disperso]: el índice y los datos no se almacenan juntos (como el índice MyISAM myz / myd y la separación de datos)
    • Las consultas de índice agrupadas son más rápidas que las consultas de índice no agrupadas
      Inserte la descripción de la imagen aquí
    • B + Tree puede almacenar más datos que B-Tree
    • Tenga en cuenta usar la clave principal para remodelar el incremento automático
      Inserte la descripción de la imagen aquí

1.1 Índice MyISAM

1.2 índice InnoDB

Crear tabla de datos InnoDB

CREATE TABLE `abc_innodb`
(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a`  int(11)     DEFAULT NULL,
  `b`  int(11)     DEFAULT NULL,
  `c`  varchar(10) DEFAULT NULL,
  `d`  varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_abc` (`a`, `b`, `c`)
) ENGINE = InnoDB;

INSERT INTO abc_innodb(a,b,c) VALUES (1,4,2);
INSERT INTO abc_innodb(a,b,c) VALUES (8,5,6);
INSERT INTO abc_innodb(a,b,c) VALUES (6,7,5);
INSERT INTO abc_innodb(a,b,c) VALUES (4,7,3);
INSERT INTO abc_innodb(a,b,c) VALUES (4,7,2);
INSERT INTO abc_innodb(a,b,c) VALUES (9,2,1);
INSERT INTO abc_innodb(a,b,c) VALUES (19,6,2);
INSERT INTO abc_innodb(a,b,c) VALUES (10,1,9);

1.3 El principio de coincidencia más a la izquierda

最左前缀匹配原则和联合索引的索引存储结构和检索方式是有关系的。

在组合索引树中,最底层的叶子节点按照第一列a列从左到右递增排列,但是b列和c列是无序的,b列只有在a列值相等的情况下小范围内递增有序,而c列只能在a,b两列相等的情况下小范围内递增有序。

就像上面的查询,B+树会先比较a列来确定下一步应该搜索的方向,往左还是往右。如果a列相同再比较b列。但是如果查询条件没有a列,B+树就不知道第一步应该从哪个节点查起。

可以说创建的idx_abc(a,b,c)索引,相当于创建了(a)、(a,b)(a,b,c)三个索引。、

组合索引的最左前缀匹配原则:使用组合索引查询时,mysql会一直向右匹配直至遇到范围查询(>、<、between、like)就停止匹配

2. Tipo de índice

2.1 Índice de clave primaria

Cada tabla InnodDB tiene un índice agrupado. El índice agrupado se construye usando B + Tree, y los datos almacenados en los nodos hoja son una fila completa de registros. En general, un índice agrupado es equivalente a un índice de clave principal. Cuando una tabla no crea un índice de clave principal, InnoDB creará automáticamente un campo RowID para construir un índice agrupado. Las reglas específicas para la creación automática de índices son las siguientes:


 1. 在表上定义主键 PRIMARY KEY,InnoDB将主键索引引用聚簇索引
 2.如果没有定义主键,InooDB会选择第一个不为NULL的唯一索引列用作聚簇索引 
 3.如果以上两个都没有,InnoDB会使用一个6 byte长整型的随机字段ROWID字段构建聚簇
 索引。该ROWID字段会在插入新行时自动递增

Todos los índices, excepto los índices agrupados, se denominan índices secundarios. En InnoDB, los datos almacenados en el nodo hoja del índice auxiliar son el valor de clave principal de la fila. Durante la recuperación, InnoDB usa este valor de clave principal para buscar filas en el índice agrupado.

Los nodos de hoja del índice de clave principal almacenarán filas de datos y el índice secundario solo almacenará el valor de clave principal.

2.2 Índice ordinario

El tipo de índice básico en MySql, no hay restricciones y está permitido insertar valores duplicados y valores nulos en la columna de índice definida

2.3 Índice único

El valor de la columna de índice debe ser único, pero se permiten valores nulos.

2.4 Índice de texto completo

Solo puede crear índices de texto completo en campos de tipo de texto CHAR, VARCHAR, TEXT. Cuando la longitud más corta es relativamente grande, si crea un índice normal, la eficiencia de una consulta difusa similar es relativamente baja, entonces puede crear una -índice de texto en MyISAM e InnoDB. Usar índice de texto completo

2.5 Índice espacial

Mysql admite la indexación espacial después de 5.7 y admite el modelo de datos geométricos de OpenGIS. MySql sigue las reglas del modelo de datos geométricos de OpenGIS en términos de indexación espacial

2.6 índice de prefijo

Al crear un índice en tipos de texto como CHAR, VARCHAR y TEXT, puede especificar la longitud de la columna de índice, pero no se puede determinar el tipo numérico

2.7 Índice de una sola columna

Índice creado por un solo campo (una tabla puede tener hasta 16 índices y la longitud máxima de bytes es 256)

2.8 Índice combinado (índice conjunto)

Un índice compuesto por varios campos se denomina índice compuesto (el uso de un índice compuesto debe seguir el principio de coincidencia de prefijo situado más a la izquierda. Generalmente, un índice compuesto se utiliza para reemplazar varios índices de una sola columna cuando las condiciones lo permiten).

Índice conjunto, al crear un índice, intente juzgar si un índice conjunto se puede utilizar en varios índices de una sola columna. El uso del índice conjunto no solo ahorra espacio, sino que también facilita el uso de la cobertura del índice.

Imagínese, cuantos más campos se indexen, ¿es más fácil cumplir con los datos devueltos por la consulta? Por ejemplo, el índice conjunto (a_b_c) equivale a tener tres índices: a, a_b y a_b_c. ¿Esto ahorra espacio? Por supuesto, el espacio ahorrado no es tres veces mayor que los tres índices (a, a_b, a_b_c), porque los datos del árbol de índice no han cambiado, pero los datos del campo de datos de índice sí se guardan.

El principio de creación de índices conjuntos , al crear un índice conjunto, debe colocar columnas de uso frecuente y columnas altamente diferenciadas al principio . El uso frecuente significa una utilización de índice alta y una discriminación alta significa una granularidad de filtrado grande. Todas estas se crean en el índice. Los escenarios de optimización que deben tenerse en cuenta también se pueden agregar al índice conjunto en los campos que a menudo deben devolverse como consultas. Si agrega un campo al índice conjunto y usa el índice de cobertura, entonces tenga en cuenta usar el índice conjunto

El uso de índice conjunto

  1. Considere si hay varios índices de una sola columna que se pueden combinar. Si es así, cree varios índices de una sola columna como un índice conjunto
  2. Actualmente, hay todas las columnas que se usan con frecuencia como campos de retorno. En este momento, puede considerar si la columna actual también se puede agregar al índice existente, de modo que la declaración de consulta pueda usar el índice de cobertura

Inserte la descripción de la imagen aquí

select * from abc_innodb where a = 13 and b = 16 and c = 4;

Inserte la descripción de la imagen aquí

CREATE TABLE `abc_innodb`
(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a`  int(11)     DEFAULT NULL,
  `b`  int(11)     DEFAULT NULL,
  `c`  varchar(10) DEFAULT NULL,
  `d`  varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_abc` (`a`, `b`, `c`)
) ENGINE = InnoDB;

2.9 Índice de cobertura (no estructura de índice)

El índice de cobertura no quiere decir que sea una estructura de índice, el índice de cobertura es un método de optimización muy común. Porque cuando usamos el índice auxiliar, solo podemos obtener el valor de la clave principal, que es equivalente a obtener los datos y necesita consultar el índice de la clave principal en base a la clave principal y luego obtener los datos. Pero imagina la siguiente situación: al consultar el índice compuesto en la tabla abc_innodb anterior, si solo necesito el campo abc, ¿eso significa que podemos devolver directamente el nodo hoja del índice compuesto sin necesidad de devolver la tabla. Esta situación es el índice de cobertura.
Inserte la descripción de la imagen aquí

3. Estructura de datos del índice

3.1 tabla hash

Tabla hash, HashMap en Java, TreeMap es la estructura de la tabla Hash, que almacena datos en forma de pares clave-valor. Usamos la tabla Hash para almacenar los datos de la tabla. Key puede almacenar columnas de índice y Value puede almacenar registros de fila o direcciones de disco de fila. La consulta equivalente a la tabla hash es muy eficiente y la complejidad de tiempo es O (1); pero no admite la búsqueda rápida de rango, y la búsqueda de rango es solo escaneando toda la tabla
(obviamente, esto no es adecuado para búsquedas frecuentes y rangos. índice de base de datos utilizado para la búsqueda.)

3.2 Búsqueda de árbol binario

La siguiente figura es un ejemplo de un
Inserte la descripción de la imagen aquí
árbol binario Las características de un árbol binario: cada nodo tiene como máximo 2 ramas, y el orden de datos del subárbol izquierdo y del subárbol derecho es pequeño de izquierda a derecha.
Esta característica es para asegurar que cada búsqueda se pueda dividir a la mitad y reducir el número de IO, pero el árbol binario es una prueba del valor del primer nodo raíz porque es fácil tener una situación en la que no queremos que ocurra. esta característica. "El árbol no está bifurcado". Es incómodo

Como se muestra abajo

Inserte la descripción de la imagen aquí

3.3 Árbol binario equilibrado

El árbol binario balanceado adopta el método de pensamiento binario. Además de las características del árbol binario, el árbol de búsqueda del árbol binario balanceado tiene la característica principal de que los niveles de los subárboles izquierdo y derecho del árbol son como máximo diferentes. Al insertar y eliminar datos, el equilibrio del árbol binario se mantiene mediante operaciones para zurdos / diestros. No habrá ninguna situación en la que el subárbol izquierdo sea muy alto y el subárbol derecho sea muy corto

El rendimiento de usar la consulta de árbol binario balanceado está cerca del método de búsqueda binaria, la complejidad de tiempo es O (log2n) id de consulta = 6, solo se requieren dos operaciones de E / S.
Inserte la descripción de la imagen aquí
Problemas con el árbol binario balanceado:

  1. La complejidad del tiempo está relacionada con la altura del árbol. Debe recuperarse tantas veces como el árbol, y la lectura de cada nodo corresponde a una operación de E / S de disco. La altura del tío es igual al número de operaciones de E / S del disco cada vez que se consultan los datos. Se necesitan 10 ms para que cada disco busque la espada del libro. Cuando la cantidad de datos de la tabla es grande, el rendimiento de la consulta será deficiente. (1 millón de volumen de datos, log2n es aproximadamente igual al tiempo de E / S de 20 discos 20 * 10 = 0,2 ms)
  2. El árbol binario equilibrado no admite la consulta de rango ni la búsqueda rápida. La consulta de rango debe atravesar varias veces desde el nodo raíz y la eficiencia de la consulta no es alta

3.4 árbol B (reconstrucción de árbol binario)

mysql的数据是存储在磁盘文件中的,查询处理数据时,需要先把磁盘中的数据加载到内存中,磁盘IO操作非常耗时
,所以我们优化的重点就是减少磁盘的IO操作。访问二叉树的每个节点就会发生一次IO如果想要减少磁盘IO操作就要
降低树的高度。

假如key为bigint=8byte 每个节点有两个指针,每个指针为4个byte 一个节点占用的空间16个byte(8+4*2=16)

因为每次在Mysqk的InnoDB存储引擎一次IO会读取的一页默认(16kb)的数据量,而二叉树一次IO有效数据量只有16byte
,空间利用率极低为了最大化利用一次IO空间一个简单的想法是在每个节点存储多个元素 在每个节点尽可能多的存储数
据。每个节点可以存储1000个索引(16k/16=1000),这样就将二叉树改造成了多叉树,通过增加树的叉树,将树
从高变成了矮胖。构建一百万条数据,树的高度只需要2层就可以了(1000*1000=100万) 也就说只需要进行两次IO
操作就能拿到数据 磁盘IO次数减少查询数据的效率也就提高了

B树是一种多叉平衡查找树

 1. B树的节点中存储着多个元素,每个内节点有多个分叉
 2. 节点中的元素包含键值和数据,节点中的键值从大到小进行排列也就是说在所有节点都能存储数据
 3. 父节点当中的元素不会出现在子节点
 4. 所有叶子节点都位于同一层,叶子节点具有相同的的深度,叶节点之间没有指针连接

Inserte la descripción de la imagen aquí
Por ejemplo, consulta datos en el árbol b:

Supongamos que consultamos datos con un valor igual a 10. Ruta de consulta bloque de disco 1-> bloque de disco 2-> bloque de disco 5.

E / S del primer disco: Cargue el bloque de disco 1 en la memoria, recorra la comparación desde el principio en la memoria, 10 <15, vaya a la izquierda, hasta el bloque de disco de direccionamiento del disco 2.

E / S del segundo disco: cargue el bloque de disco 2 en la memoria, recorra la comparación desde el principio en la memoria, 7 <10, y ubique el bloque de disco 5 en el disco.

El tercer disco IO: cargue el bloque de disco 5 en la memoria, recorra y compare en la memoria desde el principio, 10 = 10, encuentre 10, obtenga datos, si el registro de fila almacenado por datos, recupere datos, la consulta finaliza. Si se almacena la dirección del disco, los datos deben recuperarse del disco de acuerdo con la dirección del disco y la consulta finaliza.

En comparación con el árbol de búsqueda equilibrada binaria, en todo el proceso de búsqueda, aunque el número de comparaciones de datos no se reduce significativamente, el número de E / S de disco se reducirá considerablemente. Al mismo tiempo, dado que nuestra comparación se realiza en la memoria, la comparación que lleva mucho tiempo es insignificante. La altura del árbol B es generalmente de 2 a 3 capas para satisfacer la mayoría de los escenarios de aplicación, por lo que usar el árbol B para construir un índice puede mejorar la eficiencia de la consulta.

El proceso es el siguiente:

Inserte la descripción de la imagen aquí
El problema es que el árbol B todavía se puede transformar


 1. B树同样不支持范围查询的快速查找 就意味着当你进行范围查找时还是会从根节点去挨个遍历 可想而知其
 查询效率还是很低
 2. 如果data存储的是行记录,行的大小随着列数的增多,所占用的空间就会变大,这时一个页中可存储的数据量
 就会变少,树相应就会变高,磁盘IO次数就会变多

3.5 árbol B + (árbol B +, transformación del árbol B)

B + Tree es una versión mejorada de B-tree. Sobre la base de B-tree, Mysql continúa transformándolo y usa B + Tree para construir índices. La principal diferencia entre el árbol B + TreeB es si los nodos que no son hojas almacenan datos


 1. B树:非叶子节点和叶子节点都会存储数据
 2. B+Tree :只有叶子节点会存储数据,非叶子节点只存储键值。叶子节点之间使用双向指针来连接,最底层的
 叶子节点形成了一个双向有序的列表

Inserte la descripción de la imagen aquí
El nodo de la hoja inferior del árbol B + contiene todos los elementos del índice. Se puede ver en la figura que cuando B + Tree busca datos, debido a que los datos se almacenan en el nodo hoja más bajo, cada vez que la búsqueda necesita recuperar el nodo hoja para consultar los datos, entonces necesitamos consultar los datos. Cada E / S de disco está directamente relacionada con la altura del árbol, pero por otro lado, debido a que los datos se colocan en el nodo hijo, el número de índices almacenados por el bloqueo del bloque de disco para el índice aumentará en relación con el árbol B , La altura del árbol B + es teóricamente más corta que la del árbol B. También existe cobertura de índice. Los datos del índice cumplen con todos los datos requeridos por la declaración de consulta actual. En este momento, solo necesita encontrar el indexar y regresar inmediatamente., No es necesario recuperar el nodo de la hoja inferior

3.5.1 por ejemplo: consulta equivalente

Supongamos que consultamos datos con un valor igual a 9. Ruta de consulta bloque de disco 1-> bloque de disco 2-> bloque de disco 6

El primer E / S de disco: cargue el bloque de disco 1 en la memoria, recorra la comparación desde el principio en la memoria, 9 <15 vaya a la izquierda, hasta el bloque de disco de direccionamiento de disco 2

E / S del segundo disco: cargue el bloque de disco 2 en la memoria, recorra y compare desde el principio en la memoria, 7 <9 <12, y ubique el bloque de disco 6 en el direccionamiento del disco

El tercer disco IO: cargue el bloque de disco 6 en la memoria, compárelo desde el principio en la memoria, busque 9 en el tercer índice y obtenga los datos. Si el registro de datos de la fila está almacenado, obtenga los datos y la consulta finaliza. Si el almacenamiento es una dirección de disco, también necesita obtener los datos del disco de acuerdo con la dirección del disco, y la consulta se termina (la distinción aquí es que los datos almacenados en InnoDB son datos de fila y la dirección del disco se almacena en MyIsam)
como se muestra a continuación

Inserte la descripción de la imagen aquí

3.5.2 Consulta de rango

Suponga que queremos encontrar datos entre 9 y 26. La ruta de búsqueda es bloque de disco 1-> bloque de disco 2-> bloque de disco 6-> bloque de disco 7.

Primero busque los datos con el valor igual a 9 y almacene en caché los datos con el valor igual a 9 en el conjunto de resultados. Este paso es el mismo que el proceso de consulta equivalente anterior, se han producido tres operaciones de E / S de disco

Después de encontrar 15, el nodo de la hoja inferior es una lista ordenada. Comenzamos desde el bloque de disco 6 y el valor clave 9 y recorremos hacia atrás para filtrar todos los datos que cumplen las condiciones.

E / S del cuarto disco: localice el bloque de disco 7 de acuerdo con el puntero posterior del bloque de disco 6 al direccionamiento del disco, cargue el disco 7 en la memoria y recorra la comparación en la memoria desde el principio, 9 <25 <26, 9 <26 <= 26 almacenar datos en caché en el conjunto de resultados

Debido a que la clave principal es única (no habrá datos <= 26 más adelante), no es necesario continuar buscando la consulta para terminar y devolver el resultado

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_43565087/article/details/109200610
Recomendado
Clasificación