Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédente | |||
elearning:workbooks:mysql:my08 [2020/02/21 08:05] – supprimée admin | elearning:workbooks:mysql:my08 [2023/11/20 12:51] (Version actuelle) – created admin | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | **Version**: | ||
+ | ======SER407 - Optimisation====== | ||
+ | |||
+ | =====Matériel===== | ||
+ | |||
+ | ====Processeur==== | ||
+ | |||
+ | La vitesse d'un processeur est la caractéristique la plus importante. Il n'est pas possible de paralléliser une requête sur plusieurs processeurs. Pour cette raison, une requête occupe un processeur à la fois. Prenons le cas d'un serveur esclave dans le contexte d'une réplication. Toutes les requêtes de réplication passeront par un seul processeur, rendant les autres processeurs éventuels inutiles. | ||
+ | |||
+ | ====Mémoire==== | ||
+ | |||
+ | La mémoire est un facteur critique pour le serveur MariaDB. La donnée la plus importante est la quantité de données consultées. Prenons le cas d'une base de données de 20Go où seules les données de la dernière semaine sont consultées. Si ces données ne représentent que 1Go, un serveur muni de 2Go suffira largement. | ||
+ | |||
+ | ====Disque Dur==== | ||
+ | |||
+ | Les performances d'un disque dur se mesurent avec deux paramètres, | ||
+ | |||
+ | =====Système d' | ||
+ | |||
+ | MariaDB est disponible pour Windows(tm), | ||
+ | |||
+ | =====Cache de Requêtes===== | ||
+ | |||
+ | Le cache des requêtes est utilisé par MariaDB lors des requêtes de type SELECT. Le cache est utile dans le cas où la majorité des requêtes sont de type lecture. Lors d'un SELECT, MariaDB vérifie si la requête est déjà dans le cache. Cette vérification est faite pour **toutes** les requêtes, mêmes celles qui sont **impropres**. Il ne faut donc **pas** activer le cache quand : | ||
+ | |||
+ | * les écritures sont nombreuses, | ||
+ | * les lectures ne sont pas répétées, | ||
+ | * le requêtes sont en grande partie **impropre**. | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +------------------+-------+ | ||
+ | | Variable_name | ||
+ | +------------------+-------+ | ||
+ | | query_cache_type | ON | | ||
+ | +------------------+-------+ | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Cette option peut prendre trois valeurs : | ||
+ | |||
+ | * **ON** : le serveur essaie de mettre en cache toutes les requêtes SELECT sauf celles comportant la phrase SQL_NO_CACHE, | ||
+ | * **OFF** : aucune requête n'est mise en cache, | ||
+ | * **DEMAND** : le serveur essaie de mettre en cache toutes les requêtes SELECT comportant la phrase SQL_CACHE. | ||
+ | |||
+ | ====Exclusions==== | ||
+ | |||
+ | Seules les requêtes dites déterministes peuvent être mises en cache. Par exemple, une requête de type SELECT * FROM table donnera toujours le même résultat tant que la table n'est pas modifiée. Cette requête peut être mise dans le cache. Par contre la requête SELECT CURRENT_TIMESTAMP() est non-déterministe. Par conséquent, | ||
+ | |||
+ | ====Requêtes==== | ||
+ | |||
+ | MariaDB recherche dans le cache chaque fois qu'il y a une requête SELECT. MariaDB est sensible à la case. Pour cette raison, MariaDB considère que les trois requêtes suivantes sont différentes : | ||
+ | |||
+ | * SELECT prenom,nom FROM familles, | ||
+ | * select prenom,nom FROM familles, | ||
+ | * SELECT nom,prenom FROM familles. | ||
+ | |||
+ | ====Invalidations==== | ||
+ | |||
+ | Le serveur MariaDB met à jour automatiquement le contenu du cache. Lors d'une modification d'une table au niveau de sa structure ou bien au niveau de ses données, le serveur MariaDB cherche l' | ||
+ | |||
+ | ====Effacements==== | ||
+ | |||
+ | Dans le cas où le cache n'est pas suffisant pour stocker une requête, MariaDB procède a un effacement de l' | ||
+ | |||
+ | ====Fragmentation==== | ||
+ | |||
+ | MariaDB divise le cache en blocs mémoire d'une taille égale. Quand une requête est mise en cache, le serveur MariaDB ne connaît pas à l' | ||
+ | |||
+ | ====Paramètres==== | ||
+ | |||
+ | Les options associées avec le cache sont : | ||
+ | |||
+ | ^ Option ^ Descripton ^ | ||
+ | | query_cache_size | La taille de la mémoire dédiée au cache. La mémoire est affectée par multiples de 1 024 octets. Dans la pratique il ne faut pas dépasser les 256 Mo. | | ||
+ | | query_cache_limit | La taille maximale d'une requête qui peut être mise en cache | | ||
+ | | query_cache_type| Indique le type de cache | | ||
+ | | query_cache_min_res_unit | La taille des blocs de mémoire du cache | | ||
+ | | query_cache_wlock_invalidate | Quand cette option est **OFF**, le serveur peut renvoyer le contenu du cache même si la table est verrouillée par un autre utilisateur | | ||
+ | |||
+ | ====Verification du Cache==== | ||
+ | |||
+ | Pour consulter la configuration du cache, utilisez la requête suivante : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +-------------------------+-------+ | ||
+ | | Variable_name | ||
+ | +-------------------------+-------+ | ||
+ | | Qcache_free_blocks | ||
+ | | Qcache_free_memory | ||
+ | | Qcache_hits | ||
+ | | Qcache_inserts | ||
+ | | Qcache_lowmem_prunes | ||
+ | | Qcache_not_cached | ||
+ | | Qcache_queries_in_cache | 0 | | ||
+ | | Qcache_total_blocks | ||
+ | +-------------------------+-------+ | ||
+ | 8 rows in set (0.01 sec) | ||
+ | </ | ||
+ | |||
+ | Cette configuration s' | ||
+ | |||
+ | ^ Option ^ Descripton ^ | ||
+ | | Qcache_free_memory | ||
+ | | Qcache_lowmem_prunes | Le nombre d' | ||
+ | | Qcache_hits | ||
+ | |||
+ | Les valeurs ci-dessus doivent être comparées avec le nombre total de requêtes de type SELECT : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +---------------+-------+ | ||
+ | | Variable_name | Value | | ||
+ | +---------------+-------+ | ||
+ | | Com_select | ||
+ | +---------------+-------+ | ||
+ | 1 row in set (0.00 sec) | ||
+ | </ | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | 100 * Qcache_hits / Com_select | ||
+ | </ | ||
+ | |||
+ | Le taux d' | ||
+ | |||
+ | < | ||
+ | 100 * Qcache_inserts / Com_select | ||
+ | </ | ||
+ | |||
+ | La fragmentation peut être evaluée par le formule : | ||
+ | |||
+ | < | ||
+ | Qcache_free_blocks / Qcache_total_blocks | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Pour défragmenter le cache, il convient d' | ||
+ | </ | ||
+ | |||
+ | |||
+ | =====Optimisation du Schéma===== | ||
+ | |||
+ | L' | ||
+ | |||
+ | * Plus le type de données est petit et compact, plus il sera léger et performant, | ||
+ | * Évitez des colonnes NULL car cela demande plus de travail au serveur que des colonnes NOT NULL, | ||
+ | * Utilisez des champs adéquats aux besoins réels de la donnée à stocker, | ||
+ | * Ne surdimensionnez pas les champs de texte car MariaDB utilise la taille maximale pour effectuer des tris. Privilégiez donc des champs VARCHAR par rapport CHAR car ce dernier a une longueur fixe. | ||
+ | |||
+ | ====PROCEDURE ANALYSE==== | ||
+ | |||
+ | Afin de vous aider, MariaDB fournit une commande capable d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------------+ | ||
+ | | Database | ||
+ | +--------------------+ | ||
+ | | information_schema | | ||
+ | | CarnetAdresses | ||
+ | | ligue1 | ||
+ | | mysql | | ||
+ | | performance_schema | | ||
+ | | test | | ||
+ | +--------------------+ | ||
+ | 6 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | +------------------+ | ||
+ | | Tables_in_ligue1 | | ||
+ | +------------------+ | ||
+ | | equipe | ||
+ | | rencontre | ||
+ | +------------------+ | ||
+ | 2 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | | ||
+ | Create Table: CREATE TABLE `equipe` ( | ||
+ | `id_equipe` int(11) NOT NULL AUTO_INCREMENT, | ||
+ | `nom` varchar(50) NOT NULL, | ||
+ | `stade` varchar(50) NOT NULL, | ||
+ | `ville` varchar(30) NOT NULL, | ||
+ | `points` int(11) NOT NULL DEFAULT ' | ||
+ | `buts` int(11) NOT NULL DEFAULT ' | ||
+ | PRIMARY KEY (`id_equipe`) | ||
+ | ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | | ||
+ | Min_value: 1 | ||
+ | Max_value: 3 | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: 0.8165 | ||
+ | Optimal_fieldtype: | ||
+ | *************************** 2. row *************************** | ||
+ | | ||
+ | Min_value: Debian AC | ||
+ | Max_value: Vista FC | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: NULL | ||
+ | Optimal_fieldtype: | ||
+ | *************************** 3. row *************************** | ||
+ | | ||
+ | Min_value: Parc des Princes | ||
+ | Max_value: Yankee Stadium | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: NULL | ||
+ | Optimal_fieldtype: | ||
+ | *************************** 4. row *************************** | ||
+ | | ||
+ | Min_value: New York | ||
+ | Max_value: Redmond | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: NULL | ||
+ | Optimal_fieldtype: | ||
+ | *************************** 5. row *************************** | ||
+ | | ||
+ | Min_value: 0 | ||
+ | Max_value: 0 | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: 0.0000 | ||
+ | Optimal_fieldtype: | ||
+ | *************************** 6. row *************************** | ||
+ | | ||
+ | Min_value: 0 | ||
+ | Max_value: 0 | ||
+ | | ||
+ | | ||
+ | | ||
+ | Nulls: 0 | ||
+ | Avg_value_or_avg_length: | ||
+ | Std: 0.0000 | ||
+ | Optimal_fieldtype: | ||
+ | 6 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | =====Normalisation===== | ||
+ | |||
+ | La normalisation d'une base de données consiste en la structuration des objets de façon à obtenir un modèle de données performant et sur. | ||
+ | |||
+ | Les trois règles les plus importantes sont : | ||
+ | |||
+ | * Eviter des colonnes qui se répètent, | ||
+ | * Eviter l’incohérence des données, | ||
+ | * Tous les champs doivent dépendre uniquement de la clef primaire. | ||
+ | |||
+ | ====LAB #1 - Normalisation==== | ||
+ | |||
+ | Créez la base de données **connaissances** : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | MariaDB [(none)]> | ||
+ | Database changed | ||
+ | </ | ||
+ | |||
+ | Utilisez la requête suivante pour créer la table **employe** : | ||
+ | |||
+ | < | ||
+ | CREATE TABLE employe ( | ||
+ | id int(11) NOT NULL, | ||
+ | nom varchar(30) NOT NULL DEFAULT '', | ||
+ | ville varchar(30) NOT NULL DEFAULT '', | ||
+ | savoir1 varchar(30) NOT NULL DEFAULT '', | ||
+ | niv1 tinyint(4) NOT NULL, | ||
+ | savoir2 varchar(30) NOT NULL DEFAULT '', | ||
+ | niv2 tinyint(4) NOT NULL, | ||
+ | PRIMARY KEY (id) | ||
+ | ) ENGINE=InnoDB; | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> id int(11) NOT NULL, | ||
+ | -> nom varchar(30) NOT NULL DEFAULT '', | ||
+ | -> ville varchar(30) NOT NULL DEFAULT '', | ||
+ | -> savoir1 varchar(30) NOT NULL DEFAULT '', | ||
+ | -> niv1 tinyint(4) NOT NULL, | ||
+ | -> savoir2 varchar(30) NOT NULL DEFAULT '', | ||
+ | -> niv2 tinyint(4) NOT NULL, | ||
+ | -> PRIMARY KEY (id) | ||
+ | -> ) ENGINE=InnoDB; | ||
+ | Query OK, 0 rows affected (0.06 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Utilisez la requête suivante pour injecter des données : | ||
+ | |||
+ | < | ||
+ | INSERT INTO employe (id , nom , ville , savoir1 , niv1 , savoir2 , niv2) VALUES (' | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | |||
+ | Query OK, 1 row affected (0.01 sec) | ||
+ | |||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | </ | ||
+ | |||
+ | Vous devez obtenir le résultat suivant : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +----+---------+---------+---------+------+---------+------+ | ||
+ | | id | nom | ville | savoir1 | niv1 | savoir2 | niv2 | | ||
+ | +----+---------+---------+---------+------+---------+------+ | ||
+ | | 1 | Alex | Londres | Linux | ||
+ | | 2 | Mathieu | Paris | Apache | ||
+ | | 3 | Thomas | ||
+ | +----+---------+---------+---------+------+---------+------+ | ||
+ | 3 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | =====Indexes===== | ||
+ | |||
+ | Un index est une structure de données liée à une table dont le rôle est de permettre le serveur de trouver une référence au plus vite. | ||
+ | |||
+ | Un index peut être créé à la création de la table avec la clause KEY ou INDEX ou bien après sa création avec une des commandes suivantes : | ||
+ | |||
+ | CREATE INDEX nom_index ON table (colonne); | ||
+ | |||
+ | ALTER TABLE table ADD INDEX (colonne); | ||
+ | |||
+ | Ces deux commandes on des différences : | ||
+ | |||
+ | * Avec CREATE INDEX le nom de l' | ||
+ | * Avec ALTER TABLE si le nom de l' | ||
+ | * Avec ALTER TABLE il est possible de créer plusieurs index en même temps en séparant les clauses ADD INDEX par des virgules. | ||
+ | |||
+ | Pour supprimer un index on utilise une des deux commandes suivantes : | ||
+ | |||
+ | DROP INDEX nom_index | ||
+ | |||
+ | ALTER TABLE nom_index | ||
+ | |||
+ | ====Types d' | ||
+ | |||
+ | ===Index Uniques=== | ||
+ | |||
+ | Un index unique comporte une contrainte. Toutes les valeurs non NULL doivent être unique. Par contre il est possible d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Reading table information for completion of table and column names | ||
+ | You can turn off this feature to get a quicker startup with -A | ||
+ | |||
+ | Database changed | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | ERROR 1062 (23000): Duplicate entry ' | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.02 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +------+ | ||
+ | | id | | ||
+ | +------+ | ||
+ | | NULL | | ||
+ | | NULL | | ||
+ | | 1 | | ||
+ | +------+ | ||
+ | 3 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ===Clef Primaires=== | ||
+ | |||
+ | Une Clef Primaire ressemble à un index unique mais possède deux différences : | ||
+ | |||
+ | * Il ne peut y avoir qu'une Clef Primaire par table, | ||
+ | * Une Clef Primaire ne peut pas contenir des valeurs NULL. | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.03 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.06 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | </ | ||
+ | |||
+ | ===Index sur Plusieurs Colonnes=== | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.33 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.11 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | MariaDB est capable d' | ||
+ | </ | ||
+ | |||
+ | ===Index sur un Préfixe de Colonne=== | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.94 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | ERROR 1170 (42000): BLOB/TEXT column ' | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.10 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Pour les index stockant du texte, il est possible de ne créer l' | ||
+ | </ | ||
+ | |||
+ | ===Clefs Etrangères=== | ||
+ | |||
+ | Une clef étrangère indique à MariaDB de rejeter tout ajout ou modification dans la table enfant si la valeur de la clef n'a pas de correspondance dans la table parent. | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> id INT(11) NOT NULL AUTO_INCREMENT, | ||
+ | -> nom VARCHAR(20) NOT NULL DEFAULT'', | ||
+ | -> PRIMARY KEY (id), | ||
+ | -> KEY index_nom (nom) | ||
+ | -> ) ENGINE = InnoDB; | ||
+ | Query OK, 0 rows affected (0.32 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.31 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | La clause CONSTRAINT est optionnelle. Le nom de la contrainte doit être unique dans toute la base. Le nom de l' | ||
+ | </ | ||
+ | |||
+ | Lors d'une suppression ou d'une mise à jour, le comportement est dicté par l' | ||
+ | |||
+ | * **RESTRICT** ou **NO ACTION** - C'est l' | ||
+ | * **CASCADE** - Quand une ligne est mise à jour ou supprimée de la table parente, la ou les lignes corrspondantes dans la table enfant sont mises à jour ou supprimées, | ||
+ | * **SET NULL** - Quand une ligne est mise à jour ou supprimée de la table parente, la ou les lignes corrspondantes dans la table enfant sont mises à NULL. | ||
+ | |||
+ | ===Index Cluster avec InnoDB=== | ||
+ | |||
+ | Le moteur InnoDB stocke les données **avec** la clef primaire. Par conséquent toute requête qui utilise la clef primaire est très efficace. Par contre toute requête qui utilise une clef secondaire est moins efficace car MariaDB recherche d' | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans le cas où une clef primaire n' | ||
+ | </ | ||
+ | |||
+ | ===Index Couvrant=== | ||
+ | |||
+ | Dans le cas où toutes les données nécessaires à la résolution d'une requête se trouvent dans un index, on parle d'un index **couvrant**. Dans ce cas, l' | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Un index peut être créé avec un de deux algorithmes principaux : B-Tree ou Hash. Un index couvrant est forcément de type B-Tree. | ||
+ | </ | ||
+ | |||
+ | ===Index FULLTEXT=== | ||
+ | |||
+ | Dans le cas où il est nécessaire de rechercher une chaîne de caractères dans un champs, on doit utiliser un index FULLTEXT : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> col1 VARCHAR(50), | ||
+ | -> col2 VARCHAR(50), | ||
+ | -> col3 VARCHAR(50), | ||
+ | -> FULLTEXT index_col1_col2 (col1,col2) | ||
+ | -> ); | ||
+ | ERROR 1214 (HY000): The used table type doesn' | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Le moteur InnoDB supporte les index FULLTEXT à partir de la version 5.6 de MariaDB. | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.04 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.07 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.02 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Téléchargez la base de donnée exemple sakila : | ||
+ | |||
+ | < | ||
+ | [root@centos ~]# wget http:// | ||
+ | --2014-02-01 11: | ||
+ | Résolution de downloads.mysql.com... 137.254.60.14 | ||
+ | Connexion vers downloads.mysql.com|137.254.60.14|: | ||
+ | requête HTTP transmise, en attente de la réponse...200 OK | ||
+ | Longueur: 722633 (706K) [application/ | ||
+ | Sauvegarde en : «sakila-db.tar.gz» | ||
+ | |||
+ | 100%[======================================> | ||
+ | |||
+ | 2014-02-01 11:46:30 (50,6 KB/s) - «sakila-db.tar.gz» sauvegardé [722633/ | ||
+ | </ | ||
+ | |||
+ | Editez le fichier ~/ | ||
+ | |||
+ | < | ||
+ | [root@centos7 ~]# vi ~/ | ||
+ | </ | ||
+ | |||
+ | Installez sakila : | ||
+ | |||
+ | < | ||
+ | [root@centos ~]# tar xvf sakila-db.tar.gz | ||
+ | sakila-db/ | ||
+ | sakila-db/ | ||
+ | sakila-db/ | ||
+ | sakila-db/ | ||
+ | [root@centos ~]# mysql -uroot -p < sakila-db/ | ||
+ | Enter password: | ||
+ | [root@centos ~]# mysql -uroot -p < sakila-db/ | ||
+ | Enter password: | ||
+ | </ | ||
+ | |||
+ | ==Mode Langage Naturel== | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Reading table information for completion of table and column names | ||
+ | You can turn off this feature to get a quicker startup with -A | ||
+ | |||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | -> LEFT(description, | ||
+ | -> MATCH(title, | ||
+ | -> AGAINST(' | ||
+ | -> FROM film_text | ||
+ | -> WHERE MATCH(title, | ||
+ | -> AGAINST(' | ||
+ | -> LIMIT 5; | ||
+ | +---------+--------------------------------+-------------------+ | ||
+ | | film_id | LEFT(description, | ||
+ | +---------+--------------------------------+-------------------+ | ||
+ | | 113 | A Thrilling Yarn of a Database | 6.662790775299072 | | ||
+ | | 962 | A Fanciful Story of a Database | 6.662790775299072 | | ||
+ | | 27 | A Amazing Reflection of a Data | 6.662790775299072 | | ||
+ | | 363 | A Fast-Paced Display of a Car | 4.527374267578125 | | ||
+ | | 372 | A Taut Display of a Cat And a | 4.527374267578125 | | ||
+ | +---------+--------------------------------+-------------------+ | ||
+ | 5 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Par défaut une requête FULLTEXT est une recherches en langage naturel. Ceci implique que chaque mot de la clause AGAINST est recherché dans l' | ||
+ | </ | ||
+ | |||
+ | ==Mode Booléen== | ||
+ | |||
+ | En utilisant le mode booléen, il vous est possible d' | ||
+ | |||
+ | ^ Modificateur ^ Description ^ | ||
+ | | + | Le résultat doit contenir ce mot | | ||
+ | | - | Le résultat ne doit pas contenir ce mot | | ||
+ | | ~ | La pertinence de ce mot est plus faible que les autres mots | | ||
+ | | | La pertinence de ce mot est plus haute que les autres mots | | ||
+ | | * | Placé à la fin d'une chaine, ce modificateur est un joker | | ||
+ | |||
+ | Par exemple : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | film_id: 23 | ||
+ | title: ANACONDA CONFESSIONS | ||
+ | description: | ||
+ | *************************** 2. row *************************** | ||
+ | film_id: 315 | ||
+ | title: FINDING ANACONDA | ||
+ | description: | ||
+ | 2 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Notez que seulement deux résultats sont retournés. En effet, il n'y a que deux enregistrements dans la base qui contiennent le mot Anaconda. Notez que les mots faisant partie de au moins 50% des enregistrements **ne** sont **pas** automatiquement ignorés. | ||
+ | </ | ||
+ | |||
+ | ==Mode Expansion de Requête== | ||
+ | |||
+ | Dans ce mode, la recherche est lancée deux fois. La première fois avec les mots de la clause AGAINST, la deuxième avec les mots ainsi que les résultats les plus pertinents. | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +---------+------------------------+----------------------------------------------------------------------------------------------------------------------+ | ||
+ | | film_id | title | description | ||
+ | +---------+------------------------+----------------------------------------------------------------------------------------------------------------------+ | ||
+ | | 428 | HOMICIDE PEACH | A Astounding Documentary of a Hunter And a Boy who must Confront a Boy in A MariaDB Convention | ||
+ | | 577 | MILE MULAN | A Lacklusture Epistle of a Cat And a Husband who must Confront a Boy in A MariaDB Convention | ||
+ | | 812 | SMOKING BARBARELLA | ||
+ | | 936 | VANISHING ROCKY | A Brilliant Reflection of a Man And a Woman who must Conquer a Pioneer in A MariaDB Convention | ||
+ | | 494 | KARATE MOON | A Astounding Yarn of a Womanizer And a Dog who must Reach a Waitress in A MariaDB Convention | ||
+ | | 608 | MURDER ANTITRUST | ||
+ | | 341 | FROST HEAD | A Amazing Reflection of a Lumberjack And a Cat who must Discover a Husband in A MariaDB Convention | ||
+ | | 773 | SEABISCUIT PUNK | A Insightful Saga of a Man And a Forensic Psychologist who must Discover a Mad Cow in A MariaDB Convention | ||
+ | | 242 | DOOM DANCING | ||
+ | | 819 | SONG HEDWIG | ||
+ | | 15 | ALIEN CENTER | ||
+ | | 137 | CHARADE DUFFEL | ||
+ | | 844 | STEERS ARMAGEDDON | ||
+ | | 119 | CAPER MOTIONS | ||
+ | | 907 | TRANSLATION SUMMER | ||
+ | | 899 | TOWERS HURRICANE | ||
+ | | 918 | TWISTED PIRATES | ||
+ | | 933 | VAMPIRE WHALE | A Epic Story of a Lumberjack And a Monkey who must Confront a Pioneer in A MariaDB Convention | ||
+ | | 716 | REAP UNFAITHFUL | ||
+ | | 727 | RESURRECTION SILVERADO | A Epic Yarn of a Robot And a Explorer who must Challenge a Girl in A MariaDB Convention | ||
+ | | 809 | SLIPPER FIDELITY | ||
+ | | 567 | MEET CHOCOLATE | ||
+ | | 129 | CAUSE DATE | A Taut Tale of a Explorer And a Pastry Chef who must Conquer a Hunter in A MariaDB Convention | ||
+ | | 261 | DUFFEL APOCALYPSE | ||
+ | | 213 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MariaDB Convention | ||
+ | | 11 | ALAMO VIDEOTAPE | ||
+ | | 201 | CYCLONE FAMILY | ||
+ | | 352 | GATHERING CALENDAR | ||
+ | | 398 | HANOVER GALAXY | ||
+ | | 426 | HOME PITY | A Touching Panorama of a Man And a Secret Agent who must Challenge a Teacher in A MariaDB Convention | ||
+ | | 72 | BILL OTHERS | ||
+ | | 845 | STEPMOM DREAM | A Touching Epistle of a Crocodile And a Teacher who must Build a Forensic Psychologist in A MariaDB Convention | ||
+ | | 870 | SWARM GOLD | A Insightful Panorama of a Crocodile And a Boat who must Conquer a Sumo Wrestler in A MariaDB Convention | ||
+ | | 466 | INTOLERABLE INTENTIONS | A Awe-Inspiring Story of a Monkey And a Pastry Chef who must Succumb a Womanizer in A MariaDB Convention | ||
+ | | 974 | WILD APOLLO | ||
+ | | 980 | WIZARD COLDBLOODED | ||
+ | | 551 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MariaDB Convention | ||
+ | | 987 | WORDS HUNTER | ||
+ | | 183 | CONVERSATION DOWNHILL | ||
+ | | 804 | SLEEPING SUSPECTS | ||
+ | | 576 | MIGHTY LUCK | A Astounding Epistle of a Mad Scientist And a Pioneer who must Escape a Database Administrator in A MariaDB Convention | | ||
+ | | 733 | RIVER OUTLAW | ||
+ | | 303 | FANTASY TROOPERS | ||
+ | | 937 | VARSITY TRIP | A Action-Packed Character Study of a Astronaut And a Explorer who must Reach a Monkey in A MariaDB Convention | ||
+ | | 782 | SHAKESPEARE SADDLE | ||
+ | | 114 | CAMELOT VACATION | ||
+ | | 971 | WHALE BIKINI | ||
+ | | 822 | SOUP WISDOM | ||
+ | | 107 | BUNCH MINDS | A Emotional Story of a Feminist And a Feminist who must Escape a Pastry Chef in A MariaDB Convention | ||
+ | | 750 | RUN PACIFIC | ||
+ | +---------+------------------------+----------------------------------------------------------------------------------------------------------------------+ | ||
+ | 50 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | ... | ||
+ | | 113 | CALIFORNIA BIRDS | A Thrilling Yarn of a Database Administrator And a Robot who must Battle a Database Administrator in Ancient India | | ||
+ | | 617 | NATURAL STOCK | A Fast-Paced Story of a Sumo Wrestler And a Girl who must Defeat a Car in A Baloon Factory | ||
+ | | 424 | HOLOCAUST HIGHBALL | ||
+ | | 589 | MODERN DORADO | ||
+ | | 432 | HOPE TOOTSIE | ||
+ | | 145 | CHISUM BEHAVIOR | ||
+ | | 41 | ARSENIC INDEPENDENCE | ||
+ | | 751 | RUNAWAY TENENBAUMS | ||
+ | | 962 | WASTELAND DIVINE | ||
+ | | 177 | CONNECTICUT TRAMP | A Unbelieveable Drama of a Crocodile And a Mad Cow who must Reach a Dentist in A Shark Tank | | ||
+ | | 627 | NORTH TEQUILA | ||
+ | | 702 | PULP BEVERLY | ||
+ | | 511 | LAWRENCE LOVE | A Fanciful Yarn of a Database Administrator And a Mad Cow who must Pursue a Womanizer in Berlin | ||
+ | | 376 | GRAPES FURY | A Boring Yarn of a Mad Cow And a Sumo Wrestler who must Meet a Robot in Australia | ||
+ | | 430 | HOOK CHARIOTS | ||
+ | | 267 | EAGLES PANKY | A Thoughtful Story of a Car And a Boy who must Find a A Shark in The Sahara Desert | ||
+ | | 968 | WEREWOLF LOLA | A Fanciful Story of a Man And a Sumo Wrestler who must Outrace a Student in A Monastery | ||
+ | | 692 | POTLUCK MIXED | A Beautiful Story of a Dog And a Technical Writer who must Outgun a Student in A Baloon | ||
+ | | 192 | CROSSING DIVORCE | ||
+ | | 752 | RUNNER MADIGAN | ||
+ | | 448 | IDAHO LOVE | A Fast-Paced Drama of a Student And a Crocodile who must Meet a Database Administrator in The Outback | ||
+ | | 996 | YOUNG LANGUAGE | ||
+ | +---------+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------+ | ||
+ | 999 rows in set (0.02 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ==Configuration== | ||
+ | |||
+ | Une recherche FULLTEXT peut être configurée en modifiant les trois variables suivants : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +-----------------+-------+ | ||
+ | | Variable_name | ||
+ | +-----------------+-------+ | ||
+ | | ft_min_word_len | 4 | | ||
+ | +-----------------+-------+ | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +-----------------+-------+ | ||
+ | | Variable_name | ||
+ | +-----------------+-------+ | ||
+ | | ft_max_word_len | 84 | | ||
+ | +-----------------+-------+ | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Empty set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | La dernière variable peut contenir une liste de mots qui ne seront pas indexés. Notez que chaque fois que vous modifiez une des ces variables, il est nécessaire de reconstruire l' | ||
+ | </ | ||
+ | |||
+ | ==Limitations== | ||
+ | |||
+ | Veuillez garder en tête les points suivants : | ||
+ | |||
+ | * Pour effectuer une recherche FULLTEXT, il **faut** utiliser MATCH AGAINST, | ||
+ | * Dès que vous utilisez MATCH AGAINST, le serveur utilisera une recherche FULLTEXT même si l' | ||
+ | * Les résultats en mode langage naturel sont triés par la pertinence. Ceci n'est **pas** le cas pour les deux autres modes, | ||
+ | * Un index FULLTEXT ne peut **pas** être utilisé comme index couvrant. | ||
+ | |||
+ | =====La Commande EXPLAIN===== | ||
+ | |||
+ | La commande EXPLAIN est utilisée pour voir le plan d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: film_text | ||
+ | type: fulltext | ||
+ | possible_keys: | ||
+ | key: idx_title_description | ||
+ | key_len: 0 | ||
+ | ref: | ||
+ | rows: 1 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | La sortie de la commande démontre 10 colonnes dont les plus importantes sont **type**, **possible_keys**, | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Pour l' | ||
+ | </ | ||
+ | |||
+ | ====La Colonne type==== | ||
+ | |||
+ | Cette colonne montre comment l' | ||
+ | |||
+ | ===ALL=== | ||
+ | |||
+ | Un parcours complet de la table est nécessaire car il n'y a pas d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: film_text | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 1000 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | film_id: 886 | ||
+ | title: THEORY MERMAID | ||
+ | description: | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ===index=== | ||
+ | |||
+ | Un parcours complet d'un index est necéssaire : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: category | ||
+ | type: index | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 1 | ||
+ | ref: NULL | ||
+ | rows: 16 | ||
+ | Extra: Using index | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | category_id: | ||
+ | *************************** 2. row *************************** | ||
+ | category_id: | ||
+ | *************************** 3. row *************************** | ||
+ | category_id: | ||
+ | *************************** 4. row *************************** | ||
+ | category_id: | ||
+ | *************************** 5. row *************************** | ||
+ | category_id: | ||
+ | *************************** 6. row *************************** | ||
+ | category_id: | ||
+ | *************************** 7. row *************************** | ||
+ | category_id: | ||
+ | *************************** 8. row *************************** | ||
+ | category_id: | ||
+ | *************************** 9. row *************************** | ||
+ | category_id: | ||
+ | *************************** 10. row *************************** | ||
+ | category_id: | ||
+ | *************************** 11. row *************************** | ||
+ | category_id: | ||
+ | *************************** 12. row *************************** | ||
+ | category_id: | ||
+ | *************************** 13. row *************************** | ||
+ | category_id: | ||
+ | *************************** 14. row *************************** | ||
+ | category_id: | ||
+ | *************************** 15. row *************************** | ||
+ | category_id: | ||
+ | *************************** 16. row *************************** | ||
+ | category_id: | ||
+ | 16 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ===range=== | ||
+ | |||
+ | Un parcours d'une partie d'un index est nécessaire : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: category | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 1 | ||
+ | ref: NULL | ||
+ | rows: 1 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Empty set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ===index_merge=== | ||
+ | |||
+ | Plusieurs index sont utilisés simultanément : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: index_merge | ||
+ | possible_keys: | ||
+ | key: idx_fk_inventory_id, | ||
+ | key_len: 3,4 | ||
+ | ref: NULL | ||
+ | rows: 8557 | ||
+ | Extra: Using sort_union(idx_fk_inventory_id, | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | ... | ||
+ | *************************** 13776. row *************************** | ||
+ | | ||
+ | | ||
+ | inventory_id: | ||
+ | | ||
+ | | ||
+ | staff_id: 1 | ||
+ | | ||
+ | *************************** 13777. row *************************** | ||
+ | | ||
+ | | ||
+ | inventory_id: | ||
+ | | ||
+ | | ||
+ | staff_id: 1 | ||
+ | | ||
+ | *************************** 13778. row *************************** | ||
+ | | ||
+ | | ||
+ | inventory_id: | ||
+ | | ||
+ | | ||
+ | staff_id: 1 | ||
+ | | ||
+ | *************************** 13779. row *************************** | ||
+ | | ||
+ | | ||
+ | inventory_id: | ||
+ | | ||
+ | | ||
+ | staff_id: 2 | ||
+ | | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | ===ref=== | ||
+ | |||
+ | Un index non unique est examiné. Plusieurs lignes peuvent être retournées : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: const | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 2 | ||
+ | ref: const | ||
+ | rows: 1 | ||
+ | Extra: Using index | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: ref | ||
+ | possible_keys: | ||
+ | key: idx_fk_customer_id | ||
+ | key_len: 2 | ||
+ | ref: const | ||
+ | rows: 32 | ||
+ | Extra: | ||
+ | 2 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 2. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 3. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 4. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 5. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 6. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 7. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 8. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 9. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 10. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 11. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 12. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 13. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 14. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 15. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 16. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 17. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 18. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 19. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 20. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 21. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 22. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 23. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 24. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 25. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 26. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 27. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 28. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 29. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 30. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 31. row *************************** | ||
+ | rental_date: | ||
+ | *************************** 32. row *************************** | ||
+ | rental_date: | ||
+ | 32 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Il existe une variante de ref, appelé ref_or_null. Dans ce cas, il y a une deuxième passe pour retrouver les valeurs NULL. | ||
+ | </ | ||
+ | |||
+ | ===eq_ref=== | ||
+ | |||
+ | Un index unique ou une clé primaire est examiné : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: rental_date | ||
+ | key_len: 8 | ||
+ | ref: NULL | ||
+ | rows: 1 | ||
+ | Extra: Using where; Using index | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: eq_ref | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 2 | ||
+ | ref: sakila.rental.customer_id | ||
+ | rows: 1 | ||
+ | Extra: | ||
+ | 2 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Ce type est le meilleur t(ype d' | ||
+ | </ | ||
+ | |||
+ | ===Cas Spécifiques=== | ||
+ | |||
+ | ==const== | ||
+ | |||
+ | Une seule ligne a besoin d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: category | ||
+ | type: const | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 1 | ||
+ | ref: const | ||
+ | rows: 1 | ||
+ | Extra: | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | category_id: | ||
+ | name: Action | ||
+ | last_update: | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ==System== | ||
+ | |||
+ | Identique au type précédent dans le cas où la table est une table à une seule ligne. | ||
+ | |||
+ | ==NULL== | ||
+ | |||
+ | Aucun parcours de table ou d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: NULL | ||
+ | type: NULL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: NULL | ||
+ | Extra: Select tables optimized away | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | COUNT(*): 1000 | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ====Les Colonnes possible_keys, | ||
+ | |||
+ | La colonne **possible_keys** contient l' | ||
+ | |||
+ | Une valeur NULL dans la colonne **possible_keys** indique qu'il n' | ||
+ | |||
+ | La colonne **key_len** indique la taille en octets de l' | ||
+ | |||
+ | Téléchargez la base de données exemple **world** : | ||
+ | |||
+ | < | ||
+ | [root@centos ~]# wget https:// | ||
+ | </ | ||
+ | |||
+ | Installez la base de données exemple **world** : | ||
+ | |||
+ | < | ||
+ | [root@centos ~]# mysql -uroot -p | ||
+ | Enter password: | ||
+ | Welcome to the MariaDB monitor. | ||
+ | Your MariaDB connection id is 8 | ||
+ | Server version: 5.5.33-cll-lve MariaDB Community Server (GPL) by Atomicorp | ||
+ | |||
+ | Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. | ||
+ | |||
+ | Oracle is a registered trademark of Oracle Corporation and/or its | ||
+ | affiliates. Other names may be trademarks of their respective | ||
+ | owners. | ||
+ | |||
+ | Type ' | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Bye | ||
+ | [root@centos ~]# gunzip world-db.tar.gz | ||
+ | [root@centos ~]# mysql -uroot -p world < world-db/ | ||
+ | Enter password: | ||
+ | [root@centos ~]# | ||
+ | </ | ||
+ | |||
+ | Voyons un exemple maintenant avec cette base de données : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Reading table information for completion of table and column names | ||
+ | You can turn off this feature to get a quicker startup with -A | ||
+ | |||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 4079 rows affected (0.11 sec) | ||
+ | Records: 4079 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: City | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: idx_name_district | ||
+ | key_len: 35 | ||
+ | ref: NULL | ||
+ | rows: 141 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Notez que la taille de l' | ||
+ | </ | ||
+ | |||
+ | ====La Colonne rows==== | ||
+ | |||
+ | La colonne **rows** contient une estimation du nombre de lignes que le moteur doit parcourir avant de pouvoir retourner un résultat de la requête : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: Country | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 239 | ||
+ | Extra: | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: City | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 4079 | ||
+ | Extra: Using join buffer | ||
+ | 2 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans l' | ||
+ | </ | ||
+ | |||
+ | Pour prouver qu'il s'agit bien d'une estimation, saisissez la requête suivante : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: City | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: idx_name_district | ||
+ | key_len: 35 | ||
+ | ref: NULL | ||
+ | rows: 141 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.05 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | COUNT(*): 110 | ||
+ | 1 row in set (0.02 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Si vous vous rendez compte que les estimations sont largement erronées vous pouvez utilisez la commande ANALYZE TABLE pour mettre à jour les statistiques sur la table. D'une manière générale, plus élevée est la valeur de **rows**, plus lente sera la requête. | ||
+ | </ | ||
+ | |||
+ | ====La Colonne extra==== | ||
+ | |||
+ | La colonne extra donne des informations supplémentaires concernant la requête : | ||
+ | |||
+ | * **Using where** - visible quand le serveur n'a pas pu résoudre une clause WHERE en utilisant un index, | ||
+ | * **Using index** - le serveur va utiliser un index couvrant, | ||
+ | * **Using temporary** - le serveur va utiliser une table temporaire pour effectuer un tri, | ||
+ | * **Using filesort** - le serveur doit trier les résultats de la requête. | ||
+ | |||
+ | =====La Commande EXPLAIN EXTENDED===== | ||
+ | |||
+ | La commande **EXPLAIN EXTENDED** est disponible dans MariaDB depuis la version 5.1. EXPLAIN EXTENDED donne une approximation, | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: City | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 4 | ||
+ | ref: NULL | ||
+ | rows: 50 | ||
+ | | ||
+ | Extra: Using where; Using index | ||
+ | 1 row in set, 1 warning (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | COUNT(ID): 49 | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Par contre cette valeur n'est qu'une estimation : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: City | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 4079 | ||
+ | | ||
+ | Extra: Using where | ||
+ | 1 row in set, 1 warning (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | Name: Besançon | ||
+ | 1 row in set (0.07 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Malgré le peu de fiabilité dans le résultat de la colonne **filtered**, | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: NULL | ||
+ | type: NULL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: NULL | ||
+ | | ||
+ | Extra: Select tables optimized away | ||
+ | 1 row in set, 1 warning (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | Level: Note | ||
+ | Code: 1003 | ||
+ | Message: select count(0) AS `COUNT(*)` from `world`.`Country` | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | =====Optimisation des Requêtes===== | ||
+ | |||
+ | ====Isolation des Colonnes==== | ||
+ | |||
+ | L' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Reading table information for completion of table and column names | ||
+ | You can turn off this feature to get a quicker startup with -A | ||
+ | |||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 15629 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: rental_date | ||
+ | key_len: 8 | ||
+ | ref: NULL | ||
+ | rows: 1 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | La réécriture de la requête sans encapsuler une colonne dans une fonction produit une requête plus performante ( range > ALL ). | ||
+ | </ | ||
+ | |||
+ | ====Jointures==== | ||
+ | |||
+ | Quand MariaDB effectue des jointures il le fait une à une et successivement. Par exemple, dans le cas de 4 tables, table1, table2, table3, table4, la table1 est jointe à la table2 produisant une table table12. La table12 est ensite jointe à la table3 produisant la table123. La table123 est ensuite jointe à la table4 pour produire la table1234. | ||
+ | |||
+ | Dans le cas d'un INNER JOIN, MariaDB peut décider de ne pas respecter cet ordre : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: rental_date | ||
+ | key_len: 8 | ||
+ | ref: NULL | ||
+ | rows: 1 | ||
+ | Extra: Using where; Using index | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: eq_ref | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 2 | ||
+ | ref: sakila.rental.customer_id | ||
+ | rows: 1 | ||
+ | Extra: | ||
+ | 2 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | L' | ||
+ | </ | ||
+ | |||
+ | Pourquoi l' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 577 | ||
+ | Extra: | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: range | ||
+ | possible_keys: | ||
+ | key: rental_date | ||
+ | key_len: 8 | ||
+ | ref: NULL | ||
+ | rows: 1 | ||
+ | Extra: Using where; Using index; Using join buffer | ||
+ | 2 rows in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Dans le cas ci-dessus, l' | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Pour les jointure externes, LEFT JOIN et RIGHT JOIN, l' | ||
+ | </ | ||
+ | |||
+ | ====Indexes==== | ||
+ | |||
+ | ===USE INDEX=== | ||
+ | |||
+ | Il est possible d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 577 | ||
+ | Extra: | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: ref | ||
+ | possible_keys: | ||
+ | key: idx_fk_customer_id | ||
+ | key_len: 2 | ||
+ | ref: sakila.customer.customer_id | ||
+ | rows: 13 | ||
+ | Extra: Using where | ||
+ | 2 rows in set (0.00 sec) | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans le cas d' | ||
+ | </ | ||
+ | |||
+ | ===FORCE INDEX=== | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 577 | ||
+ | Extra: | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: ref | ||
+ | possible_keys: | ||
+ | key: idx_fk_customer_id | ||
+ | key_len: 2 | ||
+ | ref: sakila.customer.customer_id | ||
+ | rows: 13 | ||
+ | Extra: Using where | ||
+ | 2 rows in set (0.01 sec) | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans le cas d' | ||
+ | </ | ||
+ | |||
+ | ===IGNORE INDEX=== | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: rental | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 15629 | ||
+ | Extra: Using where | ||
+ | *************************** 2. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: customer | ||
+ | type: eq_ref | ||
+ | possible_keys: | ||
+ | key: PRIMARY | ||
+ | key_len: 2 | ||
+ | ref: sakila.rental.customer_id | ||
+ | rows: 1 | ||
+ | Extra: | ||
+ | 2 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans le cas d' | ||
+ | </ | ||
+ | |||
+ | ====CLAUSES LENTES==== | ||
+ | |||
+ | Les clauses d’agrégation telles SUM(), MAX() et MIN() provoquent en générale des requêtes lentes car il faut lire l' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | Name: film_text | ||
+ | | ||
+ | Version: 10 | ||
+ | | ||
+ | Rows: 1000 | ||
+ | | ||
+ | Data_length: | ||
+ | Max_data_length: | ||
+ | | ||
+ | Data_free: 0 | ||
+ | | ||
+ | Create_time: | ||
+ | Update_time: | ||
+ | | ||
+ | Collation: utf8_general_ci | ||
+ | | ||
+ | | ||
+ | Comment: | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: NULL | ||
+ | type: NULL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: NULL | ||
+ | Extra: Select tables optimized away | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans le cas ci-dessus la valeur de la colonne **type** est **NULL** indiquant qu' | ||
+ | </ | ||
+ | |||
+ | ====Sous-requêtes==== | ||
+ | |||
+ | MariaDB exécute parfois très lentement des sous-requêtes. Privilégiez donc les jointures plutôt que des sous-requêtes : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Reading table information for completion of table and column names | ||
+ | You can turn off this feature to get a quicker startup with -A | ||
+ | |||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | +------------+ | ||
+ | | Language | ||
+ | +------------+ | ||
+ | | Arabic | ||
+ | | French | ||
+ | | Italian | ||
+ | | Portuguese | | ||
+ | | Spanish | ||
+ | | Turkish | ||
+ | +------------+ | ||
+ | 6 rows in set (0.03 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +------------+ | ||
+ | | Language | ||
+ | +------------+ | ||
+ | | Arabic | ||
+ | | French | ||
+ | | Italian | ||
+ | | Portuguese | | ||
+ | | Spanish | ||
+ | | Turkish | ||
+ | +------------+ | ||
+ | 6 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | ====Moteurs==== | ||
+ | |||
+ | ===MyISAM=== | ||
+ | |||
+ | Le paramètre le plus important pour le moteur MyISAM est le key_buffer_size : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +-----------------+---------+ | ||
+ | | Variable_name | ||
+ | +-----------------+---------+ | ||
+ | | key_buffer_size | 8388608 | | ||
+ | +-----------------+---------+ | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +------------------------+-------+ | ||
+ | | Variable_name | ||
+ | +------------------------+-------+ | ||
+ | | Key_blocks_not_flushed | 0 | | ||
+ | | Key_blocks_unused | ||
+ | | Key_blocks_used | ||
+ | | Key_read_requests | ||
+ | | Key_reads | ||
+ | | Key_write_requests | ||
+ | | Key_writes | ||
+ | +------------------------+-------+ | ||
+ | 7 rows in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | La variable **Key_reads** indique le nombre de requêtes de lectures qui n'ont pas pu être satisfaites par le cache. La variable **Key_read_requests** indique le nombre de lectures totale. La formule (1 - Key_reads / Key_read_requests ) * 100 donne une indication de l' | ||
+ | </ | ||
+ | |||
+ | ===InnoDB== | ||
+ | |||
+ | Les paramètres les plus importants pour le moteur **InnoDB** sont résumés dans la table suivante : | ||
+ | |||
+ | ^ Paramètre ^ Valeur Suggérée ^ | ||
+ | | innodb_buffer_pool_size | 80% de la mémoire physique de la machine | | ||
+ | | innodb_flush_log_at_trx_commit | 1 si la protection des données est primordiale, | ||
+ | |||
+ | |||
+ | =====Partitionnement===== | ||
+ | |||
+ | Le partitionnement est utilisé pour diviser les données d'une table en parties logiques selon une règle pré-établie : | ||
+ | |||
+ | * Par les données contenues dans la table. Dans ce cas on parle de partitionnement **horizontal**. Il existe 4 types possibles : | ||
+ | * **Par plages**, | ||
+ | * **Par listes**, | ||
+ | * **Par hachage**, | ||
+ | * **Par clef**, | ||
+ | * Par les colonnes de la table. | ||
+ | |||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Il est possible de faire un partitionnement vertical et un partitionnement horizontal sur la même table. Il est aussi possible de faire des partitions de partitions. | ||
+ | </ | ||
+ | |||
+ | Le partitionnement apporte trois avantages : | ||
+ | |||
+ | * Créer des tables plus grandes que la taille autorisée par un système de fichiers. Il est aussi possible de stocker des partitions à des endroits différents, | ||
+ | |||
+ | * Supprimer très rapidement des données en détruisant la partition qui les contient. Ceci s' | ||
+ | |||
+ | * Optimiser certaines requêtes car les données étant organisées dans différentes partitions. Ceci s' | ||
+ | |||
+ | ====Partitionnement Horizontal==== | ||
+ | |||
+ | ===LAB #2 - Partitionnement par Plages=== | ||
+ | |||
+ | Créez une base de données **transactions** ainsi que la table **transac** : | ||
+ | |||
+ | < | ||
+ | CREATE DATABASE transactions; | ||
+ | |||
+ | USE transactions; | ||
+ | |||
+ | CREATE TABLE transac | ||
+ | ( | ||
+ | id INT UNSIGNED PRIMARY KEY, | ||
+ | montant INT UNSIGNED NOT NULL, | ||
+ | jour DATE NOT NULL, | ||
+ | codePays ENUM(' | ||
+ | ); | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 1 row affected (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Database changed | ||
+ | MariaDB [(none)]> | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED PRIMARY KEY, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays ENUM(' | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.04 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Imaginons qu'en étudiant les requêtes des utilisateurs sur cette table sur une période probante, nous découvrons que la majorité utilise des plages de date. Dans ce cas il serait utile de partitionner la table par la valeur de la colonne **jour**. Créer donc la table partitionnée appelée **transac_part** : | ||
+ | |||
+ | < | ||
+ | CREATE TABLE transac_part | ||
+ | ( | ||
+ | id INT UNSIGNED NOT NULL, | ||
+ | montant INT UNSIGNED NOT NULL, | ||
+ | jour DATE NOT NULL, | ||
+ | codePays ENUM(' | ||
+ | ) PARTITION BY RANGE(YEAR(jour)) | ||
+ | ( | ||
+ | PARTITION p1 VALUES LESS THAN(1997), | ||
+ | PARTITION p2 VALUES LESS THAN(1998), | ||
+ | PARTITION p3 VALUES LESS THAN(1999), | ||
+ | PARTITION p4 VALUES LESS THAN(2000), | ||
+ | PARTITION p5 VALUES LESS THAN(2001), | ||
+ | PARTITION p6 VALUES LESS THAN(2002), | ||
+ | PARTITION p7 VALUES LESS THAN(2003), | ||
+ | PARTITION p8 VALUES LESS THAN(2004), | ||
+ | PARTITION p9 VALUES LESS THAN(2005), | ||
+ | PARTITION p10 VALUES LESS THAN(2006), | ||
+ | PARTITION p11 VALUES LESS THAN MAXVALUE | ||
+ | ); | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED NOT NULL, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays ENUM(' | ||
+ | -> ) PARTITION BY RANGE(YEAR(jour)) | ||
+ | -> ( | ||
+ | -> PARTITION p1 VALUES LESS THAN(1997), | ||
+ | -> PARTITION p2 VALUES LESS THAN(1998), | ||
+ | -> PARTITION p3 VALUES LESS THAN(1999), | ||
+ | -> PARTITION p4 VALUES LESS THAN(2000), | ||
+ | -> PARTITION p5 VALUES LESS THAN(2001), | ||
+ | -> PARTITION p6 VALUES LESS THAN(2002), | ||
+ | -> PARTITION p7 VALUES LESS THAN(2003), | ||
+ | -> PARTITION p8 VALUES LESS THAN(2004), | ||
+ | -> PARTITION p9 VALUES LESS THAN(2005), | ||
+ | -> PARTITION p10 VALUES LESS THAN(2006), | ||
+ | -> PARTITION p11 VALUES LESS THAN MAXVALUE | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.13 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | L' | ||
+ | </ | ||
+ | |||
+ | Créez ensuite une procédure pour injecter des données dans la table **transac** : | ||
+ | |||
+ | < | ||
+ | DELIMITER // | ||
+ | CREATE PROCEDURE remplir_transaction(nbTransacs INT) | ||
+ | BEGIN | ||
+ | DECLARE i INT DEFAULT 1; | ||
+ | DECLARE nbAlea DOUBLE; | ||
+ | DECLARE _jour DATE; | ||
+ | DECLARE _montant INT UNSIGNED; | ||
+ | DECLARE _codePays TINYINT UNSIGNED; | ||
+ | |||
+ | WHILE i <= nbTransacs DO | ||
+ | SET nbAlea = RAND(); | ||
+ | SET _jour = ADDDATE(' | ||
+ | SET _montant = FLOOR(1 + (nbAlea * 9999)); | ||
+ | SET nbAlea = RAND(); | ||
+ | SET _codePays = FLOOR(1 + (nbAlea * 6)); | ||
+ | INSERT INTO transac (id, montant, jour, codePays) VALUES (i, _montant, _jour, _codePays); | ||
+ | SET i = i + 1; | ||
+ | END WHILE; | ||
+ | END // | ||
+ | |||
+ | DELIMITER ; | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> BEGIN | ||
+ | -> DECLARE i INT DEFAULT 1; | ||
+ | -> DECLARE nbAlea DOUBLE; | ||
+ | -> DECLARE _jour DATE; | ||
+ | -> DECLARE _montant INT UNSIGNED; | ||
+ | -> DECLARE _codePays TINYINT UNSIGNED; | ||
+ | -> | ||
+ | -> WHILE i <= nbTransacs DO | ||
+ | -> SET nbAlea = RAND(); | ||
+ | -> SET _jour = ADDDATE(' | ||
+ | -> SET _montant = FLOOR(1 + (nbAlea * 9999)); | ||
+ | -> SET nbAlea = RAND(); | ||
+ | -> SET _codePays = FLOOR(1 + (nbAlea * 6)); | ||
+ | -> | ||
+ | -> SET i = i + 1; | ||
+ | -> END WHILE; | ||
+ | -> END // | ||
+ | Query OK, 0 rows affected (0.05 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Appelez ensuite la procédure et patientez 10 minutes. A l' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | ^CCtrl-C -- sending "KILL QUERY 2" to server ... | ||
+ | Ctrl-C -- query aborted. | ||
+ | MariaDB [(none)]> | ||
+ | +----------+ | ||
+ | | COUNT(*) | | ||
+ | +----------+ | ||
+ | | | ||
+ | +----------+ | ||
+ | 1 row in set (0.09 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | |||
+ | Insérez maintenant les mêmes données dans la table **transac_part** : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 191939 rows affected (3.63 sec) | ||
+ | Records: 191939 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +----------+ | ||
+ | | COUNT(*) | | ||
+ | +----------+ | ||
+ | | | ||
+ | +----------+ | ||
+ | 1 row in set (0.14 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Pour voir l' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.17 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.03 sec) | ||
+ | </ | ||
+ | |||
+ | Notez que la requête sur la table partitionnée retourne un résultat **5,67** fois plus vite que sur la table d' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: transac_part | ||
+ | | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 18035 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Notez que la valeur de la colonne **partitions** est **p3**. | ||
+ | </ | ||
+ | |||
+ | Evidemment, plus qu'il y a de partitions à consulter, moins important est le gains en performance : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 198031481 | 2268.9216 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.18 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 198031481 | 2268.9216 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.16 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Le système de partitionnement peut aussi s' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 959746672 | 5000.2692 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.16 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 959746672 | 5000.2692 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.20 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Dernièrement, | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 17680 rows affected (0.18 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.10 sec) | ||
+ | Records: 0 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | ===LAB #3 - Partitionnement par Listes=== | ||
+ | |||
+ | Imaginons maintenant que nous avons découvert que les requêtes des utilisateurs portent souvent sur continent géographique. Dans ce cas, il serait utile de faire un partitionnement par liste. Le champs crée par l' | ||
+ | |||
+ | < | ||
+ | codePays ENUM(' | ||
+ | </ | ||
+ | |||
+ | associe une valeur entière à chaque valeur du champ de type ENUM. Nous allons utiliser ce fait pour créer la table partitionnée. | ||
+ | |||
+ | Commencez par nettoyer ce que vous avez déjà fait : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.17 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.09 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Créez maintenant la table transac_part : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED NOT NULL, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays TINYINT UNSIGNED NOT NULL | ||
+ | -> ) PARTITION BY LIST(codePays) | ||
+ | -> ( | ||
+ | -> PARTITION pEurope VALUES IN (1, 2, 3), | ||
+ | -> PARTITION pAmeriqueNord VALUES IN (4, 5), | ||
+ | -> PARTITION pAsie VALUES IN (6) | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.06 sec) | ||
+ | </ | ||
+ | |||
+ | Appelez la procédure remplir_transaction et copiez la valeurs dans transac_part : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | ^CCtrl-C -- sending "KILL QUERY 2" to server ... | ||
+ | Ctrl-C -- query aborted. | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 52193 rows affected (0.57 sec) | ||
+ | Records: 52193 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Comparez le gains de performance en utilisant la table partitionnée : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 130838834 | 5018.9433 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.07 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 130838834 | 5018.9433 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.04 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Notez que la requête sur la table partitionnée retourne un résultat **1,75** fois plus vite que sur la table d' | ||
+ | |||
+ | Comparez le gains de performance en utilisant uniquement la partition numéro 6 : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.05 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Notez que la requête sur la table partitionnée retourne un résultat **5** fois plus vite que sur la table d' | ||
+ | ===LAB #4 - Partitionnement par Hash=== | ||
+ | |||
+ | Dans ce cas la partition à laquelle appartient un enregistrement est déterminée à partir de la valeur de retour d'une fonction définie par l' | ||
+ | |||
+ | Re-créez la table transac_part : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.03 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED NOT NULL, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays ENUM(' | ||
+ | -> ) PARTITION BY HASH(YEAR(jour)) PARTITIONS 11; | ||
+ | Query OK, 0 rows affected (0.07 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 52193 rows affected (0.85 sec) | ||
+ | Records: 52193 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Notez qu'ici on indique le champs de référence **jour** et le nombre de partitions désirées. | ||
+ | </ | ||
+ | |||
+ | Testez maintenant le gains de performance en utilisant les partitions : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.09 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.08 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Notez qu'ici le gains de performance est minime. | ||
+ | </ | ||
+ | |||
+ | Le gains de performance est minime parce que toutes les partitions ont été scannées : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: transac_part | ||
+ | | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 52982 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.00 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Le partitionnement par hachage n'est efficace que dans le cas ou le hash est généré à partir d'une colonne de type entier. | ||
+ | </ | ||
+ | |||
+ | Pour prouver ce point, recréez la table transac_part avec des partitions basées sur la colonne **codePays** : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.22 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED NOT NULL, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays TINYINT UNSIGNED NOT NULL | ||
+ | -> ) PARTITION BY HASH(codePays) PARTITIONS 6; | ||
+ | Query OK, 0 rows affected (0.23 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 52193 rows affected (0.65 sec) | ||
+ | Records: 52193 Duplicates: 0 Warnings: 0 | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Testez de nouveau le gain de performance en utilisant les partitions : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.04 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.02 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Cette fois-ci le gain est plus important. | ||
+ | </ | ||
+ | ===Partitionnement par Key=== | ||
+ | |||
+ | Dans ce cas la partition à laquelle appartient un enregistrement est déterminée à partir de la valeur de retour d'une fonction définie par le serveur MariaDB. | ||
+ | |||
+ | Par exemple : | ||
+ | |||
+ | < | ||
+ | CREATE TABLE transac_part | ||
+ | ( | ||
+ | id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, | ||
+ | | ||
+ | jour DATE NOT NULL, | ||
+ | | ||
+ | ) PARTITION BY KEY() PARTITIONS 5; | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | **Important** : | ||
+ | Dans ce cas, la clef n'est pas spécifiée. Le hachage est généré à partir de tous les champs de la clef primaire. Dans notre cas c'est le champ **id**. Puisqu' | ||
+ | </ | ||
+ | |||
+ | ===LAB #5 - Sous-partitionnement=== | ||
+ | |||
+ | Avec MariaDB il est possible de créer des sous-partitions. Cependant il existe deux limitations : | ||
+ | |||
+ | * La partition de premier niveau doit être de type RANGE ou LIST, | ||
+ | * La partition de deuxième niveau doit être de type HASH ou KEY, | ||
+ | * Le nombre de partitions total ne peut pas dépasser **8192**. | ||
+ | |||
+ | Prenons le cas où les requêtes fréquentes portent sur les dates **et** sur la zone géographique. | ||
+ | |||
+ | Créez la table transac-part : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | Query OK, 0 rows affected (0.18 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED NOT NULL, | ||
+ | -> montant INT UNSIGNED NOT NULL, | ||
+ | -> jour DATE NOT NULL, | ||
+ | -> codePays INT UNSIGNED NOT NULL | ||
+ | -> ) | ||
+ | -> PARTITION BY RANGE(YEAR(jour)) | ||
+ | -> SUBPARTITION BY HASH(codePays) SUBPARTITIONS 6 | ||
+ | -> ( | ||
+ | -> PARTITION p1 VALUES LESS THAN(1997), | ||
+ | -> PARTITION p2 VALUES LESS THAN(1998), | ||
+ | -> PARTITION p3 VALUES LESS THAN(1999), | ||
+ | -> PARTITION p4 VALUES LESS THAN(2000), | ||
+ | -> PARTITION p5 VALUES LESS THAN(2001), | ||
+ | -> PARTITION p6 VALUES LESS THAN(2002), | ||
+ | -> PARTITION p7 VALUES LESS THAN(2003), | ||
+ | -> PARTITION p8 VALUES LESS THAN(2004), | ||
+ | -> PARTITION p9 VALUES LESS THAN(2005), | ||
+ | -> PARTITION p10 VALUES LESS THAN(2006), | ||
+ | -> PARTITION p11 VALUES LESS THAN MAXVALUE | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (1.37 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Testez maintenant le gain de performance en utilisant les partitions : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 2928528 | 4073.0570 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.05 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 2928528 | 4073.0570 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 261035779 | 5001.3561 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.07 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +--------------+--------------+ | ||
+ | | SUM(montant) | AVG(montant) | | ||
+ | +--------------+--------------+ | ||
+ | | 261035779 | 5001.3561 | | ||
+ | +--------------+--------------+ | ||
+ | 1 row in set (0.09 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Notez la dégradation des performance avec les partitions dans le cas d'une requête sans clause WHERE : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: transac_part | ||
+ | | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 893 | ||
+ | Extra: Using where | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | *************************** 1. row *************************** | ||
+ | id: 1 | ||
+ | select_type: | ||
+ | table: transac_part | ||
+ | | ||
+ | type: ALL | ||
+ | possible_keys: | ||
+ | key: NULL | ||
+ | key_len: NULL | ||
+ | ref: NULL | ||
+ | rows: 54365 | ||
+ | Extra: | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | ====LAB #6 - Partitionnement Vertical==== | ||
+ | |||
+ | Dans ce cas les partitions sont des tables différentes. Prenons l' | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, | ||
+ | -> libelle VARCHAR(50) NOT NULL, | ||
+ | -> prix DECIMAL(10, | ||
+ | -> photo BLOB NOT NULL | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.04 sec) | ||
+ | </ | ||
+ | |||
+ | Séparez maintenant les photos des autres données : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, | ||
+ | -> libelle VARCHAR(50) NOT NULL, | ||
+ | -> prix DECIMAL(10, | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.04 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> ( | ||
+ | -> idProd INT UNIQUE NOT NULL, | ||
+ | -> photo BLOB NOT NULL | ||
+ | -> ); | ||
+ | Query OK, 0 rows affected (0.03 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | Utilisez la procédure suivante pour injecter les données : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | -> BEGIN | ||
+ | -> DECLARE i INT DEFAULT 1; | ||
+ | -> DECLARE _prix DECIMAL(10, | ||
+ | -> DECLARE _photo BLOB DEFAULT REPEAT(' | ||
+ | -> | ||
+ | -> WHILE i <= nbProds DO | ||
+ | -> SET _prix = CAST((RAND() * 1000) AS DECIMAL(10, | ||
+ | -> | ||
+ | -> | ||
+ | -> | ||
+ | -> SET i = i + 1; | ||
+ | -> END WHILE; | ||
+ | -> END // | ||
+ | Query OK, 0 rows affected (0.10 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | ^CCtrl-C -- sending "KILL QUERY 3" to server ... | ||
+ | Ctrl-C -- query aborted. | ||
+ | ERROR 1317 (70100): Query execution was interrupted | ||
+ | MariaDB [(none)]> | ||
+ | +----------+ | ||
+ | | COUNT(*) | | ||
+ | +----------+ | ||
+ | | 1664 | | ||
+ | +----------+ | ||
+ | 1 row in set (0.02 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +----------+ | ||
+ | | COUNT(*) | | ||
+ | +----------+ | ||
+ | | 1664 | | ||
+ | +----------+ | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | +----------+ | ||
+ | | COUNT(*) | | ||
+ | +----------+ | ||
+ | | 1663 | | ||
+ | +----------+ | ||
+ | 1 row in set (0.01 sec) | ||
+ | |||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | |||
+ | Testez maintenant le gain de performance en utilisant les partitions : | ||
+ | |||
+ | < | ||
+ | MariaDB [(none)]> | ||
+ | MariaDB [(none)]> | ||
+ | </ | ||
+ | |||
+ | |||
+ | ----- | ||
+ | < | ||
+ | < | ||
+ | Copyright © 2020 Hugh Norris. | ||
+ | </ | ||
+ | </ |