Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL en 2018 :contenu de la version 8.0 et autres observations

Avec la majeure partie, sinon la totalité, de 2018 derrière nous (selon le moment où vous lisez cet article), il ne fait aucun doute que ce fut une année fantastique pour les bases de données SQL open source.

PostgreSQL 11 et MySQL 8 ont tous deux été publiés, offrant aux deux communautés beaucoup de choses à 'parler '. À vrai dire, les deux fournisseurs ont introduit de nombreux changements et ajouts importants dans leurs versions respectives et méritent leurs éloges et leurs félicitations.

Je publie normalement des articles sur le premier ici sur le blog de Manynines (un grand merci à une excellente organisation !) mais je m'intéresse aussi au second. Avec de nombreux articles de blog sur mon propre site Web (lien dans ma section bio), ciblant principalement MySQL version 5.7, il (MySQL) est toujours dans mes périphériques.

Alors qu'est-ce que MySQL 8 a que la version 5.7 n'a pas ? Quelles sont les améliorations ? Eh bien, il y en a beaucoup. En fait, trop nombreux pour être couverts dans un seul article de blog.

J'ai récemment mis à niveau vers la version 8 dans mon environnement d'apprentissage/développement Linux actuel, alors j'ai pensé essayer d'en signaler quelques-uns.

Je ne peux pas vous garantir une discussion approfondie sur votre 'favori ' nouvelles fonctionnalités). En revanche, je visiterai ceux qui ont retenu mon attention soit par intérêt personnel, soit par le biais des nombreux articles de blog formidables publiés tout au long de l'année sur la version 8.

MySQL s'améliore de plus en plus... De formidables améliorations dans la version 8 !

Rôles

Avec les rôles, les DBA peuvent atténuer la redondance, où de nombreux utilisateurs partageraient le même privilège ou ensemble de privilèges.

Les rôles font partie du standard SQL.

Après avoir créé un rôle spécifique avec le ou les privilèges souhaités/requis, vous pouvez ensuite attribuer aux utilisateurs ce rôle particulier via la commande GRANT ou de la même manière, 'enlève ' avec RÉVOQUER.

Les rôles présentent de nombreux avantages et pour vous faciliter la vie, il existe quelques tableaux pour vous aider à les suivre :

  • mysql.role_edges - Vous trouverez ici ces rôles et les utilisateurs qui leur sont attribués.

    mysql> DESC mysql.role_edges;
    +-------------------+---------------+------+-----+---------+-------+
    | Field             | Type          | Null | Key | Default | Extra |
    +-------------------+---------------+------+-----+---------+-------+
    | FROM_HOST         | char(60)      | NO   | PRI |         |       |
    | FROM_USER         | char(32)      | NO   | PRI |         |       |
    | TO_HOST           | char(60)      | NO   | PRI |         |       |
    | TO_USER           | char(32)      | NO   | PRI |         |       |
    | WITH_ADMIN_OPTION | enum('N','Y') | NO   |     | N       |       |
    +-------------------+---------------+------+-----+---------+-------+
    5 rows in set (0.01 sec)
  • mysql.default_roles - Stocke tous les rôles par défaut et les utilisateurs attribués.

    mysql> DESC mysql.default_roles;
    +-------------------+----------+------+-----+---------+-------+
    | Field             | Type     | Null | Key | Default | Extra |
    +-------------------+----------+------+-----+---------+-------+
    | HOST              | char(60) | NO   | PRI |         |       |
    | USER              | char(32) | NO   | PRI |         |       |
    | DEFAULT_ROLE_HOST | char(60) | NO   | PRI | %       |       |
    | DEFAULT_ROLE_USER | char(32) | NO   | PRI |         |       |
    +-------------------+----------+------+-----+---------+-------+
    4 rows in set (0.00 sec)

La combinaison des deux tables (pas au sens SQL JOIN) fournit essentiellement un 'emplacement centralisé ' où vous pouvez :connaître, surveiller et évaluer toutes vos relations et affectations de privilèges utilisateur-rôle mises en œuvre.

L'exemple de scénario d'utilisation de rôle le plus simple serait probablement :

Vous avez plusieurs utilisateurs qui ont besoin d'un 'accès en lecture seule ' sur une table spécifique, nécessitant donc au moins le privilège SELECT. Au lieu de l'accorder (SELECT) individuellement à chaque utilisateur, vous pouvez établir (créer) un rôle ayant ce privilège, puis attribuer ce rôle à ces utilisateurs.

Mais, les rôles viennent avec un petit 'hic '. Une fois créé et attribué à un utilisateur, l'utilisateur destinataire doit avoir un ensemble de rôles actif par défaut, lors de l'authentification lors de la connexion.

Au sujet des rôles et des utilisateurs, je pense qu'il est important de mentionner le changement implémenté dans MySQL 8 concernant le composant validate_password, qui est une variante du plugin validate_password utilisé dans la version 5.7 .

Ce composant fournit différentes 'catégories distinctes ' de vérification du mot de passe :faible, moyen (par défaut) et fort. Consultez la documentation du composant validate_password pour un aperçu complet des spécificités de validation de chaque niveau.

NoSQL se mêle à SQL - Le magasin de documents

Cette fonctionnalité est celle que j'apprends encore, malgré un intérêt éphémère pour MongoDB au début de 2016. À ce jour, mon intérêt, mes études et mon apprentissage se sont concentrés uniquement sur "SQL". Cependant, je suis conscient (grâce à de nombreuses lectures sur le Web) que beaucoup sont enthousiasmés par ce type de structuration (orientée document) entrelacée avec le "SQL relationnel" désormais disponible dans le magasin de documents MySQL 8.

Vous trouverez ci-dessous de nombreux avantages disponibles lors de l'utilisation du magasin de documents. Assurez-vous de mentionner vos favoris que j'ai peut-être manqués dans la section des commentaires :

  • Le type de données JSON est pris en charge depuis la version 5.7.8 de MySQL, mais la version 8 a introduit des améliorations significatives pour travailler avec JSON. Nouvelles fonctions spécifiques à JSON avec 'raccourci ' opérateurs qui peuvent être utilisés à la place de plusieurs appels de fonction - avec des résultats/sorties égaux.
  • L'un des principaux avantages est peut-être que vous n'avez plus besoin de mettre en œuvre et d'utiliser plusieurs solutions de base de données, car NoSQL, SQL ou une combinaison des deux sont pris en charge dans le magasin de documents.
  • Une "DevAPI" fournit des fonctionnalités de flux de travail transparentes dans un contexte de données NoSQL (collections et documents). (Consultez la documentation officielle du guide de l'utilisateur DevAPI pour plus d'informations).
  • Sessions de ligne de commande puissantes utilisant Python, SQL ou Javascript comme langage "shell".
  • Conforme ACID.
  • Explorez et découvrez rapidement vos données sans définir de schéma comme vous le feriez dans un modèle relationnel.

Expressions de table communes (CTE ou clause WITH)

Que pouvez-vous dire d'autre sur les CTE ? Ces choses changent la donne ! Pour commencer, qu'est-ce qu'une expression de table commune ?

De Wikipédia :

"Une expression de table commune, ou CTE, (en SQL) est un ensemble de résultats nommé temporaire, dérivé d'une requête simple et défini dans la portée d'exécution d'une instruction SELECT, INSERT, UPDATE ou DELETE."

Je vais donner un exemple simple, démontrant les CTE. Cependant, leur pleine puissance n'est pas exploitée dans cette section, car il existe de nombreux exemples de cas d'utilisation plus complexes que ceux-ci.

J'ai une table de noms simple avec cette description et ces données :

mysql> DESC name;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| f_name | varchar(20) | YES  |     | NULL    |       |
| l_name | varchar(20) | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM name;
+--------+------------+
| f_name | l_name     |
+--------+------------+
| Jim    | Dandy      |
| Johhny | Applesauce |
| Ashley | Zerro      |
| Ashton | Zerra      |
| Ashmon | Zerro      |
+--------+------------+
5 rows in set (0.00 sec)

Découvrons combien de noms de famille commencent par 'Z' :

mysql> SELECT *
    -> FROM name
    -> WHERE l_name LIKE 'Z%';
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashley | Zerro  |
| Ashton | Zerra  |
| Ashmon | Zerro  |
+--------+--------+
3 rows in set (0.00 sec)

Assez facile.

Cependant, en utilisant la clause WITH, vous pouvez 'accéder ' ce même ensemble de résultats de requête (qui peut être considéré comme une table dérivée) et s'y référer ultérieurement dans la même instruction - ou 'portée ' :

 WITH last_Z AS (
           SELECT *
           FROM name
           WHERE l_name LIKE 'Z%')
   SELECT * FROM last_Z;
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashley | Zerro  |
| Ashton | Zerra  |
| Ashmon | Zerro  |
+--------+--------+
3 rows in set (0.00 sec)

J'attribue essentiellement un nom à la requête, en l'enveloppant entre parenthèses. Ensuite, sélectionnez simplement les données que je veux à partir de ce qui est maintenant le last_Z CTE.

Le CTE last_Z fournit un ensemble de résultats complet, vous pouvez donc le filtrer encore plus au sein de la même instruction :

WITH last_Z AS ( 
           SELECT *
           FROM name
           WHERE l_name LIKE 'Z%')
   SELECT f_name, l_name FROM last_Z WHERE l_name LIKE '%a';
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashton | Zerra  |
+--------+--------+
1 row in set (0.00 sec)

Quelques-unes des fonctionnalités les plus puissantes sont 'chaîner ' plusieurs CTE ensemble et faisant référence à d'autres CTE au sein des CTE.

Voici un exemple pour vous donner une idée (mais pas tellement utile) :

WITH last_Z AS ( 
           SELECT *
           FROM name
           WHERE l_name LIKE 'Z%'),
        best_friend AS (
           SELECT f_name, l_name
           FROM last_Z
           WHERE l_name LIKE '%a')
   SELECT * from best_friend;
+--------+--------+
| f_name | l_name |
+--------+--------+
| Ashton | Zerra  |
+--------+--------+
1 row in set (0.00 sec)

Dans la requête ci-dessus, vous pouvez voir où j'ai séparé le last_Z CTE du best_friend CTE avec une virgule, puis mis cette requête entre parenthèses après le mot-clé AS.

Remarquez que je peux alors me référer (et utiliser) le last_Z CTE pour définir essentiellement le best_friend CTE.

Voici quelques raisons pour lesquelles les CTE constituent une amélioration si significative dans la version 8 :

  • D'autres fournisseurs SQL ont pris en charge les CTE (beaucoup depuis des versions antérieures au sein de leur écosystème individuel) et maintenant MySQL 8 a comblé l'écart dans ce domaine.
  • Une inclusion SQL standard.
  • Dans certains cas (le cas échéant), les CTE sont une meilleure option que les tables temporaires, les vues, les tables dérivées (ou les vues en ligne) et certaines sous-requêtes.
  • Les CTE peuvent fournir un 'à la volée ' ensemble de résultats de calculs sur lesquels vous pouvez interroger.
  • Un CTE peut se référencer lui-même - connu sous le nom de CTE récursif (non démontré ici).
  • Les CTE peuvent nommer et utiliser d'autres CTE
ClusterControlConsole unique pour l'ensemble de votre infrastructure de base de donnéesDécouvrez les autres nouveautés de ClusterControlInstallez ClusterControl GRATUITEMENT

Fonctions de la fenêtre

Les requêtes analytiques sont désormais possibles dans MySQL 8. Les fonctions Window n'étant pas mon fort, je me concentre sur une étude plus approfondie et une meilleure compréhension de celles-ci, dans leur ensemble, pour aller de l'avant. Ces exemples suivants sont pour la plupart élémentaires selon ma compréhension. Les suggestions, les conseils et les meilleures pratiques sont les bienvenus de la part des lecteurs.

J'ai cette VIEW qui fournit un ensemble de résultats de données de tuyau fictif (quelque chose que je comprends un peu):

mysql> SELECT * FROM pipe_vw;
+---------+-------------+-----------+-------+-------------+------------+----------------+
| pipe_id | pipe_name   | joint_num | heat  | pipe_length | has_degree | wall_thickness |
+---------+-------------+-----------+-------+-------------+------------+----------------+
|     181 | Joint-278   | 39393A    | 9111  |       17.40 |          1 |          0.393 |
|     182 | Joint-8819  | 19393Y    | 9011  |       16.60 |          0 |          0.427 |
|     183 | Joint-9844  | 39393V    | 8171  |       10.40 |          0 |          0.393 |
|     184 | Joint-2528  | 34493U    | 9100  |       11.50 |          1 |          0.427 |
|     185 | Joint-889   | 18393z    | 9159  |       13.00 |          0 |          0.893 |
|     186 | Joint-98434 | 19293Q    | 8174  |        9.13 |          0 |          0.893 |
|     187 | Joint-78344 | 17QTT     | 179   |       44.40 |          1 |          0.893 |
|     188 | Joint-171C  | 34493U    | 17122 |        9.45 |          1 |          0.893 |
|     189 | Joint-68444 | 17297Q    | 6114  |       11.34 |          0 |          0.893 |
|     190 | Joint-4841R | 19395Q    | 5144  |       25.55 |          0 |          0.115 |
|     191 | Joint-1224C | 34493U    | 8575B |       15.22 |          1 |          0.893 |
|     192 | Joint-2138  | 34493C    | 91    |       13.55 |          1 |          0.893 |
|     193 | Joint-122B  | 34493U    | 9100B |        7.78 |          1 |          0.893 |
+---------+-------------+-----------+-------+-------------+------------+----------------+
13 rows in set (0.00 sec)

Imaginez, j'ai besoin des enregistrements d'actifs de tuyaux présentés dans une sorte de classement des lignes en fonction de la longueur de chaque tuyau individuel. (Par exemple, la longueur la plus longue est 'étiquetée' en position numéro 1, la deuxième longueur la plus longue est 'étiquetée' en position 2, etc...)

Basé sur la description de la fonction de fenêtre RANK() dans la documentation :

"Renvoie le rang de la ligne actuelle dans sa partition, avec des espaces. Les pairs sont considérés comme ex aequo et reçoivent le même rang. Cette fonction n'attribue pas de rangs consécutifs aux groupes de pairs s'il existe des groupes de taille supérieure à un ; le résultat est des numéros de rang non contigus ."

Il semble bien adapté à cette exigence.

mysql> SELECT pipe_name, pipe_length,
    -> RANK() OVER(ORDER BY pipe_length DESC) AS long_to_short
    -> FROM pipe_vw;
+-------------+-------------+---------------+
| pipe_name   | pipe_length | long_to_short |
+-------------+-------------+---------------+
| Joint-78344 |       44.40 |             1 |
| Joint-4841R |       25.55 |             2 |
| Joint-278   |       17.40 |             3 |
| Joint-8819  |       16.60 |             4 |
| Joint-1224C |       15.22 |             5 |
| Joint-2138  |       13.55 |             6 |
| Joint-889   |       13.00 |             7 |
| Joint-2528  |       11.50 |             8 |
| Joint-68444 |       11.34 |             9 |
| Joint-9844  |       10.40 |            10 |
| Joint-171C  |        9.45 |            11 |
| Joint-98434 |        9.13 |            12 |
| Joint-122B  |        7.78 |            13 |
+-------------+-------------+---------------+
13 rows in set (0.01 sec)

Dans le scénario suivant, je souhaite développer encore plus l'exemple précédent en classant les enregistrements des longueurs les plus longues aux plus courtes, mais pour chaque groupe individuel des valeurs distinctes de wall_thickness.

Peut-être que la requête et les résultats ci-dessous expliqueront mieux où ma prose ne l'a peut-être pas :

mysql> SELECT pipe_name, pipe_length, wall_thickness,
    -> RANK() OVER(PARTITION BY wall_thickness ORDER BY pipe_length DESC) AS long_to_short
    -> FROM pipe_vw;
+-------------+-------------+----------------+---------------+
| pipe_name   | pipe_length | wall_thickness | long_to_short |
+-------------+-------------+----------------+---------------+
| Joint-4841R |       25.55 |          0.115 |             1 |
| Joint-278   |       17.40 |          0.393 |             1 |
| Joint-9844  |       10.40 |          0.393 |             2 |
| Joint-8819  |       16.60 |          0.427 |             1 |
| Joint-2528  |       11.50 |          0.427 |             2 |
| Joint-78344 |       44.40 |          0.893 |             1 |
| Joint-1224C |       15.22 |          0.893 |             2 |
| Joint-2138  |       13.55 |          0.893 |             3 |
| Joint-889   |       13.00 |          0.893 |             4 |
| Joint-68444 |       11.34 |          0.893 |             5 |
| Joint-171C  |        9.45 |          0.893 |             6 |
| Joint-98434 |        9.13 |          0.893 |             7 |
| Joint-122B  |        7.78 |          0.893 |             8 |
+-------------+-------------+----------------+---------------+
13 rows in set (0.00 sec)

Cette requête utilise la clause PARTITION BY sur la colonne wall_thickness parce que nous voulons le classement (fourni par ORDER BY pipe_length DESC) cependant, nous en avons besoin dans le contexte des groupes wall_thickness individuels.

Chaque classement de colonne long_to_short est réinitialisé à 1 lorsque vous rencontrez (ou changez) une valeur de colonne wall_thickness différente.

Concentrons-nous sur les résultats d'un seul groupe.

En ciblant les enregistrements avec des valeurs d'épaisseur de paroi de 0,893, la ligne avec pipe_length 44,40 a un "classement" long_to_short correspondant de 1 (c'est le plus long), tandis que la ligne avec pipe_length 7,78 a un "classement" long_to_short correspondant de 8 (le plus court) tout dans ce groupe spécifique (0,893) de valeurs wall_thickness.

Les fonctions de fenêtre sont assez puissantes et leur portée et leur étendue entières ne pourraient pas être couvertes dans une seule section. N'oubliez pas de visiter les fonctions de fenêtre prises en charge dans la documentation de MySQL 8 pour plus d'informations sur celles actuellement disponibles.

Amélioration de la prise en charge et des capacités spatiales

Il s'agit d'un ensemble considérable de fonctionnalités incluses dans MySQL 8. La prise en charge des versions précédentes, ou leur absence, ne pouvait tout simplement pas être comparée aux implémentations d'autres fournisseurs (pensez à PostGIS pour PostgreSQL).

Au cours des 10 dernières années et plus, j'ai travaillé sur le terrain en tant qu'inspecteur de pipelines, collectant des données GPS et d'actifs, donc ce groupe de changements attire définitivement mon attention.

L'expertise des données spatiales est un sujet complet à part entière et rassurez-vous, je suis loin d'être un expert en la matière. Cependant, j'espère résumer les changements importants entre les versions 5.7 et 8 et les transmettre de manière claire et concise.

Familiarisons-nous avec 2 termes (et concepts) clés pour les besoins de cette section.

  1. Système de référence spatiale ou SRS - Voici une définition partielle de Wikipédia :

    "Un système de référence spatiale (SRS) ou un système de référence de coordonnées (CRS) est un système local, régional ou mondial basé sur des coordonnées utilisé pour localiser des entités géographiques. Un système de référence spatiale définit une projection cartographique spécifique, ainsi que des transformations entre différentes références spatiales. systèmes."

  2. Identificateur de système de référence spatiale ou SRID - En outre, Wikipedia définit les SRID comme tels :

    "Un identifiant de système de référence spatiale (SRID) est une valeur unique utilisée pour identifier sans ambiguïté les définitions de système de coordonnées spatiales projetées, non projetées et locales. Ces systèmes de coordonnées constituent le cœur de toutes les applications SIG."

MySQL prend en charge de nombreux types de données spatiales. L'un des plus courants est un POINT. Si vous utilisez votre GPS pour vous rendre à votre restaurant préféré, cet emplacement est un POINT sur une carte.

MySQL 5.7 traite à peu près tous les 'objets spatiaux ' comme ayant un SRID de 0, ce qui est significatif pour les calculs. Ces calculs sont effectués dans un système de coordonnées de type cartésien. Cependant, nous savons tous que notre globe est une sphère et loin d'être plat. Par conséquent, dans la version 8, vous avez la possibilité de le considérer comme plat ou sphérique dans les calculs.

Revenons à ces deux termes, que nous avons définis précédemment.

Même si 0 est le SRID par défaut dans MySQL version 8, de nombreux (environ 5 000+) autres SRID sont pris en charge.

Mais pourquoi est-ce important ?

Cette explication fantastique via le billet de blog, Systèmes de référence spatiale dans MySQL 8.0, résume bien :

"Par défaut, si nous ne spécifions pas de SRID, MySQL créera des géométries dans le SRID 0. Le SRID 0 est la notion de MySQL d'un plan catésien abstrait, sans unité et infini. Alors que tous les autres SRS se réfèrent à une surface et définissent des unités pour le axes, SRID 0 ne le fait pas."

Essentiellement, lors de l'exécution de calculs avec des SRID autres que SRID 0 , alors la forme de notre Terre entre en jeu, est prise en compte et affecte ces calculs. Ceci est crucial pour tout calcul significatif/précis. Pour un aperçu détaillé et une meilleure extrapolation, consultez cet article de blog couvrant la géographie dans MySQL 8.

Je recommande également fortement le billet de blog de l'équipe MySQL Server, Systèmes de référence spatiale géographique dans MySQL 8.0, pour plus de clarté sur les SRS. Assurez-vous de le lire !

Enfin, pour les problèmes de mise à niveau des données spatiales de la version 5.7 à la version 8, consultez certaines des modifications incompatibles répertoriées ici pour plus d'informations.

Autres observations notables

Vous trouverez ci-dessous d'autres améliorations de la version que je dois reconnaître, bien qu'elles ne soient pas traitées en détail dans cet article de blog :

  • utf8mb4 est maintenant le jeu de caractères par défaut (anciennement latin1) - Meilleur support pour ceux qui doivent avoir des emojis en plus de certaines langues...
  • Dictionnaire de données transactionnelles :les métadonnées MySQL sont désormais hébergées dans des tables InnoDB.
  • Index invisibles :définissez la visibilité d'un index pour l'optimiseur, en déterminant finalement si l'ajouter ou le supprimer (l'index) est une bonne ou une mauvaise chose. L'ajout d'un index à une grande table existante peut être 'coûteux ' en termes de verrouillage et de ressources.
  • Index décroissants – Meilleures performances sur les valeurs indexées stockées dans l'ordre décroissant.
  • Instant Add Column - Pour les modifications de schéma, spécifiez ALGORITHM=INSTANT dans les instructions ALTER TABLE et (si cela est possible pour l'opération) évitez les verrous de métadonnées. (Pour plus d'informations, consultez cet excellent article de l'équipe MySQL Server et la section ALTER TABLE de la documentation officielle.)

Section bonus :quelque chose que j'espérais voir...

Ressources associées ClusterControl pour MySQL Série de blogs "Devenir un administrateur de base de données MySQL – Opérations courantes – Modifications de la topologie de réplication Série de blogs Devenir un administrateur de base de données MySQL – Mises à niveau de la base de données

Les contraintes de vérification n'ont pas encore fait leur chemin dans le produit MySQL.

Comme avec les versions précédentes de MySQL, la syntaxe de contrainte de vérification est autorisée dans vos commandes CREATE TABLE mais elle est ignorée. À ma connaissance, la plupart des autres fournisseurs SQL prennent en charge les contraintes de vérification. Venez rejoindre la fête MySQL !

MySQL a considérablement 'renforcé ' son offre dans la version 8. La prise en charge de fonctionnalités spatiales robustes, d'options de rôle de gestion des utilisateurs pratiques, de solutions de données SQL/NoSQL "hybrides" et de fonctions analytiques parmi les nombreuses améliorations supplémentaires, est vraiment remarquable.

À mon avis, avec la version 8, MySQL continue de fournir une option solide dans l'écosystème SQL open source compétitif en constante croissance, plein de solutions pertinentes et riches en fonctionnalités.

Merci d'avoir lu.