(1) Structure de données d'optimisation d'index MySql et optimisation des performances

L'index est une structure de données triée qui aide Mysql à obtenir des données efficacement

Quel est l'indice?


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

1. Structure des données et mise en œuvre de l'index

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

AFFICHER LE STATUT GLOBAL COMME 'Innodb_page_size';
Les arbres B + avec une hauteur d'arbre de 3 peuvent stocker environ 21902400 index

  • 1. Clustered Index- [Clustered Index]: L'index et les données sont rassemblés (les nœuds feuilles contiennent des données complètes)
  • 2. Index non clusterisé - [Index fragmenté]: l'index et les données ne sont pas stockés ensemble (comme l'index MyISAM myz / myd et la séparation des données)
    • Les requêtes d'index en cluster sont plus rapides que les requêtes d'index non en cluster
      Insérez la description de l'image ici
    • B + Tree peut stocker plus de données que B-Tree
    • N'oubliez pas d'utiliser la clé primaire pour remodeler l'incrémentation automatique
      Insérez la description de l'image ici

1.1 Index MyISAM

1.2 Indice InnoDB

Créer une table de données 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 Le principe de correspondance le plus à gauche

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

在组合索引树中,最底层的叶子节点按照第一列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. Type d'index

2.1 Index de clé primaire

Chaque table InnodDB possède un index clusterisé. L'index clusterisé est construit à l'aide de B + Tree et les données stockées dans les nœuds feuilles sont une ligne entière d'enregistrements. En général, un index clusterisé équivaut à un index de clé primaire. Lorsqu'une table ne crée pas d'index de clé primaire, InnoDB crée automatiquement un champ RowID pour créer un index cluster. Les règles spécifiques pour la création automatique d'index sont les suivantes:


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

Tous les index, à l'exception des index clusterisés, sont appelés index secondaires. Dans InnoDB, les données stockées dans le nœud feuille de l'index auxiliaire sont la valeur de clé primaire de la ligne. Lors de la récupération, InnoDB utilise cette valeur de clé primaire pour rechercher des lignes dans l'index clusterisé.

Les nœuds feuilles de l'index de clé primaire stockeront les lignes de données et l'index secondaire ne stockera que la valeur de clé primaire.

2.2 Index ordinaire

Le type d'index de base dans MySql, il n'y a pas de restrictions, et il est permis d'insérer des valeurs en double et des valeurs nulles dans la colonne d'index définie

2.3 Index unique

La valeur de la colonne d'index doit être unique mais les valeurs nulles sont autorisées

2.4 Index de texte intégral

Vous ne pouvez créer des index de texte intégral que sur des champs de type texte CHAR, VARCHAR, TEXT. Lorsque la longueur la plus courte est relativement grande, si vous créez un index normal, l'efficacité d'une requête floue similaire est relativement faible, vous pouvez créer une requête complète -index de texte dans MyISAM et InnoDB. Utiliser l'index de texte intégral

2.5 Indice spatial

Mysql prend en charge l'indexation spatiale après la version 5.7 et prend en charge le modèle de données géométriques OpenGIS. MySql suit les règles du modèle de données géométriques OpenGIS en termes d'indexation spatiale

Index de préfixe 2.6

Lors de la création d'un index sur des types de texte tels que CHAR, VARCHAR et TEXT, vous pouvez spécifier la longueur de la colonne d'index, mais le type numérique ne peut pas être déterminé

2.7 Index de colonne unique

Index créé par un seul champ (une table peut avoir jusqu'à 16 index et la longueur maximale d'octet est de 256)

2.8 Indice combiné (indice conjoint)

Un index composé de plusieurs champs est appelé un index composite (l'utilisation d'un index composite doit suivre le principe de la correspondance de préfixe le plus à gauche. En général, un index composite est utilisé pour remplacer plusieurs index à une seule colonne lorsque les conditions le permettent)

Index conjoint, lors de la création d'un index, essayez de juger si un index conjoint peut être utilisé sur plusieurs index à une seule colonne. L'utilisation de l'index conjoint permet non seulement d'économiser de l'espace, mais facilite également l'utilisation de la couverture d'index.

Imaginez, plus il y a de champs indexés, est-il plus facile de rencontrer les données renvoyées par la requête? Par exemple, l'index conjoint (a_b_c) équivaut à avoir trois index: a, a_b et a_b_c. Cela permet-il d'économiser de l'espace? Bien sûr, l'espace économisé n'est pas trois fois les trois index (a, a_b, a_b_c), car les données de l'arborescence d'index n'ont pas changé, mais les données du champ de données d'index sont effectivement enregistrées.

Le principe de la création d'un index conjoint , lors de la création d'un index conjoint, vous devez placer les colonnes fréquemment utilisées et les colonnes hautement différenciées devant. Une utilisation fréquente signifie une utilisation élevée de l'index, et une discrimination élevée signifie une granularité de filtrage élevée. Elles sont toutes créées dans l'index. les scénarios d'optimisation qui doivent être pris en compte peuvent également être ajoutés à l'index conjoint sur les champs qui doivent souvent être renvoyés sous forme de requêtes. Si vous ajoutez un champ à l'index conjoint et utilisez l'index de couverture, pensez à utiliser l'index conjoint

L'utilisation de l'index conjoint

  1. Déterminez s'il existe plusieurs index à une seule colonne qui peuvent être fusionnés. Si tel est le cas, créez plusieurs index à une seule colonne en tant qu'index conjoint.
  2. Actuellement, toutes les colonnes sont fréquemment utilisées comme champs de retour. À ce stade, vous pouvez déterminer si la colonne actuelle peut également être ajoutée à l'index existant, de sorte que l'instruction de requête puisse utiliser l'index de couverture.

Insérez la description de l'image ici

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

Insérez la description de l'image ici

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 Index de couverture (pas de structure d'index)

L'index de couverture ne veut pas dire qu'il s'agit d'une structure d'index, l'index de couverture est une méthode d'optimisation très courante. Parce que lors de l'utilisation de l'index auxiliaire, nous ne pouvons obtenir que la valeur de la clé primaire, ce qui équivaut à obtenir les données et vous devez interroger l'index de clé primaire en fonction de la clé primaire, puis obtenir les données. Mais imaginez la situation suivante: lors de l'interrogation de l'index composite dans la table abc_innodb ci-dessus, si je n'ai besoin que du champ abc, cela signifie-t-il que nous pouvons directement renvoyer le nœud feuille de l'index composite sans avoir besoin de retourner .table. Cette situation est l'indice de couverture.
Insérez la description de l'image ici

3. Structure des données d'index

3.1 table de hachage

Table de hachage, HashMap en Java, TreeMap est la structure de la table de hachage, qui stocke les données sous forme de paires clé-valeur. Nous utilisons la table de hachage pour stocker les données de la table. Key peut stocker des colonnes d'index et Value peut stocker des enregistrements de ligne ou des adresses de disque de ligne. La requête équivalente à la table de hachage est très efficace et la complexité temporelle est O (1); mais elle ne prend pas en charge la recherche rapide par plage, et la recherche par plage se fait uniquement en scannant toute la table
(évidemment, cela ne convient pas à la recherche fréquente et à la plage. index de base de données utilisé pour la recherche.)

3.2 Recherche dans l'arbre binaire

La figure suivante est un exemple d'
Insérez la description de l'image ici
arbre binaire Les caractéristiques d'un arbre binaire: chaque nœud a au plus 2 branches, et l'ordre des données du sous-arbre de gauche et du sous-arbre de droite est petit de gauche à droite.
Cette fonctionnalité est de s'assurer que chaque recherche peut être divisée par deux et réduire le nombre d'E / S, mais l'arbre binaire est un test de la valeur du premier nœud racine car il est facile d'avoir une situation dans laquelle nous ne voulons pas se produire cette fonction. "L'arbre n'est pas fourchu." C'est inconfortable

Comme indiqué ci-dessous

Insérez la description de l'image ici

3.3 Arbre binaire équilibré

L'arbre binaire équilibré adopte la méthode de la pensée binaire. En plus des caractéristiques de l'arbre binaire, l'arbre de recherche d'arbre binaire équilibré a la caractéristique principale que les niveaux des sous-arbres gauche et droit de l'arbre sont au plus différents. Lors de l'insertion et de la suppression de données, l'équilibre de l'arbre binaire est maintenu grâce à des opérations gaucher / droitier., Il n'y aura pas de situation où le sous-arbre gauche est très haut et le sous-arbre droit est très court

Les performances de l'utilisation de la requête d'arbre binaire équilibré sont proches de la méthode de recherche binaire, la complexité temporelle est O (log2n) ID de requête = 6, seules deux opérations d'E / S sont nécessaires
Insérez la description de l'image ici
. Problèmes avec l'arborescence binaire équilibrée:

  1. La complexité temporelle est liée à la hauteur des arbres. Il doit être récupéré autant de fois que l'arborescence, et la lecture de chaque nœud correspond à une opération d'E / S de disque. La hauteur de l'oncle est égale au nombre d'opérations d'E / S disque à chaque fois que les données sont interrogées. Il faut 10 ms à chaque disque pour rechercher l'épée du livre. Lorsque la quantité de données de table est importante, les performances de la requête seront médiocres. (1 million de volume de données, log2n est approximativement égal à 20 temps d'E / S disque 20 * 10 = 0,2 ms)
  2. L'arborescence binaire équilibrée ne prend pas en charge la requête par plage et la recherche rapide. La requête par plage doit être traversée plusieurs fois à partir du nœud racine et l'efficacité des requêtes n'est pas élevée

3.4 B tree (reconstruction de l'arbre binaire)

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. 所有叶子节点都位于同一层,叶子节点具有相同的的深度,叶节点之间没有指针连接

Insérez la description de l'image ici
Par exemple, interrogez les données dans le b-tree:

Supposons que nous interrogions des données avec une valeur égale à 10. Bloc de disque de chemin de requête 1-> bloc de disque 2-> bloc de disque 5.

Premier disque IO: Chargez le bloc de disque 1 dans la mémoire, parcourez la comparaison depuis le début dans la mémoire, 10 <15, allez à gauche, jusqu'au bloc de disque d'adressage de disque 2.

Deuxième disque IO: chargez le bloc de disque 2 dans la mémoire, parcourez la comparaison depuis le début dans la mémoire, 7 <10, et localisez le bloc de disque 5 dans le disque.

Le troisième disque IO: chargez le bloc de disque 5 dans la mémoire, parcourez et comparez dans la mémoire depuis le début, 10 = 10, trouvez 10, récupérez des données, si l'enregistrement de ligne stocké par des données, récupérez des données, la requête se termine. Si l'adresse du disque est stockée, les données doivent être extraites du disque en fonction de l'adresse du disque et la requête est terminée.

Par rapport à l'arbre de recherche équilibré binaire, dans l'ensemble du processus de recherche, bien que le nombre de comparaisons de données ne soit pas significativement réduit, le nombre d'E / S disque sera considérablement réduit. Dans le même temps, notre comparaison étant effectuée en mémoire, la comparaison chronophage est négligeable. La hauteur de l'arborescence B est généralement de 2 à 3 couches pour répondre à la plupart des scénarios d'application, donc l'utilisation de l'arborescence B pour créer un index peut améliorer l'efficacité de la requête.

Le processus est le suivant:

Insérez la description de l'image ici
Le problème est que l'arbre B peut encore être transformé


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

3.5 Arbre B + (Arbre B +, transformation de l'arbre B)

B + Tree est une version améliorée de B-tree. Sur la base de B-tree, Mysql continue de le transformer et utilise B + Tree pour créer des index. La principale différence entre l'arbre B + TreeB est de savoir si les nœuds non-feuilles stockent des données


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

Insérez la description de l'image ici
Le nœud feuille inférieur de B + Tree contient tous les éléments d'index. On peut voir sur la figure que lorsque B + Tree recherche des données, parce que les données sont stockées sur le nœud feuille le plus bas, chaque fois que la recherche doit récupérer le nœud feuille pour interroger les données, nous devons donc interroger les données. Chaque disque IO est directement lié à la hauteur de l'arbre, mais d'un autre côté, comme les données sont placées dans le nœud enfant, le nombre d'index stockés par le verrou de bloc de disque pour l'index augmentera par rapport à l'arbre B , La hauteur de l'arborescence de B + Tree est théoriquement plus courte que celle de l'arborescence B. La couverture de l'index existe également. Les données de l'index correspondent à toutes les données requises par l'instruction de requête en cours. Pour le moment, il vous suffit de trouver le index et retour immédiatement., Pas besoin de récupérer le nœud feuille inférieur

3.5.1 par exemple: requête équivalente

Supposons que nous interrogions des données avec une valeur égale à 9. Bloc de disque de chemin de requête 1-> bloc de disque 2-> bloc de disque 6

Le premier disque IO: Chargez le bloc de disque 1 dans la mémoire, parcourez la comparaison depuis le début dans la mémoire, 9 <15 aller à gauche, vers le bloc de disque d'adressage de disque 2

Deuxième disque IO: chargez le bloc de disque 2 dans la mémoire, parcourez et comparez depuis le début dans la mémoire, 7 <9 <12, et localisez le bloc de disque 6 dans l'adressage du disque

Le troisième disque IO: chargez le bloc de disque 6 dans la mémoire, comparez-le depuis le début dans la mémoire, trouvez 9 dans le troisième index et récupérez les données. Si l'enregistrement de ligne de données est stocké, récupérez les données et la requête se termine. Si le stockage est une adresse de disque, vous devez également récupérer les données du disque en fonction de l'adresse du disque, et la requête est terminée (la distinction ici est que les données stockées dans InnoDB sont des données de ligne, et l'adresse du disque est stockée dans MyIsam)
comme indiqué ci-dessous

Insérez la description de l'image ici

3.5.2 Requête de plage

Supposons que nous voulions trouver des données entre 9 et 26. Le chemin de recherche est le bloc de disque 1-> bloc de disque 2-> bloc de disque 6-> bloc de disque 7.

Recherchez d'abord les données avec la valeur égale à 9 et mettez en cache les données avec la valeur égale à 9 dans l'ensemble de résultats. Cette étape est la même que le processus de requête équivalent précédent, trois opérations d'E / S disque ont eu lieu

Après avoir trouvé 15, le nœud feuille du bas est une liste ordonnée. Nous partons du bloc de disque 6 et de la valeur de clé 9 et parcourons en arrière pour filtrer toutes les données qui remplissent les conditions.

Quatrième disque IO: localisez le bloc de disque 7 en fonction du pointeur suivant du bloc de disque 6 vers l'adressage du disque, chargez le disque 7 dans la mémoire et parcourez la comparaison dans la mémoire depuis le début, 9 <25 <26, 9 <26 <= 26 mettre en cache les données dans l'ensemble de résultats

Étant donné que la clé primaire est unique (il n'y aura plus de données <= 26 plus tard), il n'est pas nécessaire de continuer à rechercher la requête à terminer et de renvoyer le résultat

Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/qq_43565087/article/details/109200610
conseillé
Classement