Since MySQL 5.7 one can put indexes on expressions, aka functional indexes, using generated columns. Basically you first need to use the generated column to define the functional expression, then indexed this column.
Quite useful when dealing with JSON functions, you can find an example here and the documentation there.
Starting with MySQL 8.0.13 we have now an easiest way to create functional indexes (or functional key parts as mentioned in the documentation) \o/
Let’s see how with a quick practical example.
Le 10 octobre 2013, Le MySQL User Group Francophone (lemug.fr) et Oracle MySQL vous invitent au MySQL Tech Day à Paris.
A partir de 10h30, avec un programme exceptionnel !!! :
Overview: MySQL Innovation @Oracle @MySQL Connect
Xavier GERARD / Olivier ZEMRAG (MySQL France)
MySQL Performance: Latest improvements in MySQL 5.6 & 5.7
Dimitri KRAVTCHUK (MySQL Performance Engineering leader)
MySQL Optimizer: What is new? what is coming?
Guilhem BICHOT (MySQL Optimizer Engineering team)
50 tips to boost MySQL Performance
Arnaud ADANT (MySQL Support team)
MySQL Performance Schema: Overview / HOWTO
Dimitri KRAVTCHUK(MySQL Performance Engineering leader)
MySQL Performance Schema: Hands-on (live lab)
Comme promit, voici la suite de l’article Utiliser une sous-requête c’est mal ?
L’idée ici est de répondre aux interrogations de svar et d’en profiter pour explorer les nouvelles possibilités de la variante stable de MySQL qui possède l’optimiseur le plus avancé, c’est à dire MariaDB 5.5.
Préambule
En pré-requis, je vous invite à explorer la doc officielle de MySQL au sujet de la variable optimizer_switch, qui permet de sélectionner les algorithmes d’optimisation, ainsi que les différentes subtilités implémentées dans l’optimiseur de MariaDB.
La valeur par défaut sur MariaDB 5.5.30 de la variable optimizer_switch est:
Jusqu’en MySQL 5.5 inclus, l’utilisation de sous-requêtes peut, dans certain cas, être la cause de problèmes de performances (l’optimiseur est bien meilleur en MySQL 5.6, MariaDB 5.5 et MariaDB 10).
Récemment j’ai eu un souci en prod, après une MEP, avec une requête qui durait en moyenne plus de 1000 secondes…
Inutile de préciser que dans un environnement OLTP, application web plus précisément, ce n’est pas jouable, elle a donc été virée très rapidement (mais pas le développeur qui l’a créée…)
Alors passons sur le fait que ce genre de problème devrait être identifié avant d’arriver sur la prod, et voyons à quoi ressemble une requête qui peut prendre 45 minutes:
2/ FTS ou FIS
Avant de répondre explicitement à la question, un petit zoom sur l’une des nombreuses nouveautés de MySQL 5.6. La commande EXPLAIN s’est enrichie de la clause format=json. Elle permet d’avoir une version un peu plus détaillée que l’EXPLAIN classique.
Query 1/ EXPLAIN format=json SELECT d,avg(price) FROM bills GROUP BY d\G
MySQL utilise un optimiseur à base de coûts. Le plan d’exécution de la requête choisit est celui dont le coût est le plus faible. Ce dernier peut être visualisé grâce à la variable Last_query_cost.
Son unité est le coût (encore lui) des accès aléatoires en lecture de pages de 4ko.
Étrangement cette variable est assez peu/mal documentée. Voici ce qu’on retrouve dans la doc officielle de MySQL
Je cite:
Last_query_cost
The total cost of the last compiled query as computed by the query optimizer. This is useful for comparing the cost of different query plans for the same query. The default value of 0 means that no query has been compiled yet. The default value is 0.Last_query_cost has session scope.
TheLast_query_cost value can be computed accurately only for simple “flat” queries, not complex queries such as those with subqueries orUNION. For the latter, the value is set to 0.
La valeur de Last_query_cost est parfois déconcertante, même avec MySQL 5.6. Voyez par vous même…