Pourquoi MySQL/innoDB n'utilise pas mon bel index à partir de ???

Fermé
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021 - 31 mars 2020 à 12:35
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 - 1 avril 2020 à 15:30
Bonjour,

J'ai ajouté sur une table en innoDB un index qui boost un max un select.
Il est bien utilisé sur une recherche d'une quinzaine de jours (environ) mais pas au delà !!!
Pourquoi ??! Une limitation ? de quoi ?

Comment faire pour levé cette limitation ?
Sinon comment savoir quand utiliser un autre index (moins bon) ?
(MySQL ne choisit pas le bon...)


Voir ci-dessous,
J'ai essayé avec différant intervalle de longueur et de plage de date,
c'est toujours AUX ENVIRONS de 15 jours que l'index idPlus n'est plus pris en compte.
GRRRrrr !

Merci.


PRESENTATION TABLE
------------------


mysql> show columns from Mes;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| idx | int(10) unsigned | NO | PRI | NULL | auto_increment |
| rep | int(11) | YES | MUL | NULL | |
| ind | tinyint(4) | YES | | NULL | |
| dtA | datetime(3) | YES | | NULL | |
| val | float | YES | | NULL | |
| infoI1 | int(11) | YES | | NULL | |
| infoS1 | varchar(30) | YES | | NULL | |
| dyA | int(10) unsigned | YES | MUL | 0 | |
+--------+------------------+------+-----+---------+----------------+
8 rows in set (0.01 sec)

mysql> show index from Mes;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------
| mes | 0 | PRIMARY | 1 | idx | A | 13097815 | NULL | NULL | | BTREE
| mes | 1 | idMes | 1 | rep | A | 33 | NULL | NULL | YES | BTREE
| mes | 1 | idMes | 2 | ind | A | 33 | NULL | NULL | YES | BTREE
| mes | 1 | idDyA | 1 | dyA | A | 85 | NULL | NULL | YES | BTREE
| mes | 1 | idPlus | 1 | dyA | A | 8242 | NULL | NULL | YES | BTREE
| mes | 1 | idPlus | 2 | rep | A | 15008 | NULL | NULL | YES | BTREE
| mes | 1 | idPlus | 3 | ind | A | 15008 | NULL | NULL | YES | BTREE
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------
7 rows in set (0.00 sec)

mysql> select * from Mes where dtA > '2020-02-01' limit 5;
+----------+------+------+-------------------------+----------+--------+----------------------+------------+
| idx | rep | ind | dtA | val | infoI1 | infoS1 | dyA |
+----------+------+------+-------------------------+----------+--------+----------------------+------------+
| 62405160 | 681 | 1 | 2020-02-01 00:00:00.744 | 0.146489 | 0 | STM: Mesure opacité | 1580511600 |
| 62405161 | 604 | 1 | 2020-02-01 00:00:08.195 | 1.56353 | 0 | LM: Mesure de vent | 1580511600 |
| 62405162 | 609 | 1 | 2020-02-01 00:00:17.395 | 1.44338 | 0 | LM: Mesure de vent | 1580511600 |
| 62405163 | 606 | 1 | 2020-02-01 00:00:19.296 | 1.64104 | 0 | LM: Mesure de vent | 1580511600 |
| 62405164 | 602 | 1 | 2020-02-01 00:00:19.846 | 1.43067 | 0 | LM: Mesure de vent | 1580511600 |
+----------+------+------+-------------------------+----------+--------+----------------------+------------+

mysql> select count(idx) from Mes;
+------------+
| count(idx) |
+------------+
| 13159102 |
+------------+

LE PROBLEME
-----------

mysql> explain select dtA, val FROM Mes USE INDEX(idPlus) WHERE dyA >= unix_timestamp('2020-02-01') AND dyA <= unix_timestamp('2020-02-15') AND rep=0601 AND ind=1;
+----+-------------+-------+------------+-------+---------------+--------+---------+------+---------+----------+----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+---------+----------+----------------------------------+
| 1 | SIMPLE | Mes | NULL | range | idPlus | idPlus | 12 | NULL | 2159980 | 0.30 | Using index condition; Using MRR |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+---------+----------+----------------------------------+
==> Requête super rapide... (tout est relatif...)

mysql> explain select dtA, val FROM Mes USE INDEX(idPlus) WHERE dyA >= unix_timestamp('2020-02-01') AND dyA <= unix_timestamp('2020-02-16') AND rep=0601 AND ind=1;
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| 1 | SIMPLE | Mes | NULL | ALL | idPlus | NULL | NULL | NULL | 13097815 | 0.05 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
==> Requête super lente...

8 réponses

yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
31 mars 2020 à 13:15
bonjour,
si tu fais un explain sans préciser l'index, que se passe-t'il?
idMes ne pourrait-il pas être unique?
as-tu envisagé de créer un index (rep,ind,dya)?
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
31 mars 2020 à 13:37
Si je précis pas l'index il prend idMes qui est bien moins bon ici.
IdMes ne peux pas être unique (plusieurs val par rep-ind)

Mais OUI, avec index (rep,ind,dya) c'est ok, même sur 6 mois ! Super !

mais pourquoi pas index(dya, rep,ind) ?????

Merci
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
31 mars 2020 à 13:54
je m'attendrais à ce que idMes soit meilleur que idPlus pour la requête que tu fais.
comme tu fais une requête où tu spécifies des valeurs uniques pour rep et pour ind, un index avec ces deux champs au départ est de loin plus efficace.
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
31 mars 2020 à 14:09
Oui, c'est pour ca que j'avais crée idMes !
Mais non, c'est index(rep,int, dyA) le meilleur !
Un tout petit peu moins bon que index(dyA, rep,ind) mais lui ne marche que sur 15jours...

Comme je le pensais, idMes ne peu pas être unique (plusieurs valeurs par couple rep-ind)
mysql> create unique index idMes2 on Mes (rep,ind);
ERROR 1062 (23000): Duplicate entry '637-1' for key 'idMes2'

Merci encore.
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
31 mars 2020 à 14:24
peux-tu marquer la discussion comme résolue?
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
1 avril 2020 à 10:36
.
Bonjour,
Bon, finalement, c'est pas résolu ! :

resumé:
dyA = int(10) unsigned -> contient un unix_timestamp de date (ie '2020-01-01')
dtA = datetime
val = float -> contient plein de valeur par jour (horodatées dans dtA)

idDya = index(dyA)

mysql> explain select val from mes use index(idDya) where dya>=unix_timestamp(date('2020-03-12'));
+----+-------------+-------+------------+-------+---------------+-------+---------+------+---------+----------+----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+---------+----------+----------------------------------+
| 1 | SIMPLE | mes | NULL | range | idDyA | idDyA | 5 | NULL | 2108706 | 100.00 | Using index condition; Using MRR |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+---------+----------+----------------------------------+
mysql> explain select val from mes use index(idDya) where dya>=unix_timestamp(date('2020-03-11'));
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| 1 | SIMPLE | mes | NULL | ALL | idDyA | NULL | NULL | NULL | 13089141 | 17.88 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+



Pourquoi idDya n'est pas pris au delà de 15 jours environ ?
Vous allez me dire parce qu’il n'est plus assez filtrant (trop de row) à partir de 16 jours ?
Mais pourtant il est super rapide à 15j !! Et super lent à 16j sans l'index !!
C'est MOI qui décide non ?
comment le forcer à prendre l'index pour plus de 15 jours ? (Après c'est moi qui voit quand limiter cet usage)
(ce n'est pas innodb_buffer_pool_size ... j'ai essayé)

Dois-je ajouter un champ dmA (timestamps par mois) et faire un index dessus ??!! (comme j'ai fais par jour avec dyA...)

Merci
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
Modifié le 1 avril 2020 à 10:56
super rapide et super lent: combien de temps, dans chaque cas, pour obtenir plus de 2 millions d'enregistrements?

tu écris "C'est MOI qui décide". as-tu lu la documentation?

utilises-tu régulièrement
ANALYZE TABLE
?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
1 avril 2020 à 10:59
Bin comme ça :


select val from mes use index(idDya) where dya>=unix_timestamp(date('2020-03-11'));

| 0.03296 |
| 0.253924 |
| 0.03296 |
| 0.161372 |
^C -- query aborted
+------------+
1200370 rows in set (23.20 sec)


ET

select val from mes use index(idDya) where dya>=unix_timestamp(date('2020-03-12'));

| 2.22264 |
| 2.15754 |
| 57.3626 |
| 0.0622578 |
| ^C -- query aborted
53.798 |
+------------+
1121574 rows in set (4.65 sec)


Bon ok, je remplace super rapide par relativement rapide, mais quand même...
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
1 avril 2020 à 11:05
il est en effet préférable d'être factuel.

tu écris "C'est MOI qui décide". as-tu lu la documentation?

utilises-tu régulièrement ANALYZE TABLE?
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
1 avril 2020 à 12:31
>il est en effet préférable d'être factuel.
oui !

>tu écris "C'est MOI qui décide". as-tu lu la documentation?
Je visite beaucoup de site sur le sujet et je lis l'aide.
Cela dit, je ne suis, comme beaucoup, qu'un humble informaticien 'touche à tout' mais expert en rien...
'c'est MOI qui décide' veux dire que j'aimerai choisir l'index en fonction du contexte d'utilisation du user...


>utilises-tu régulièrement ANALYZE TABLE?
Heuuu, non.
Mais je pense que les insert remettent les indexes à jour. Non ?
Je l'ai fait là, mais ça ne change rien...

Merci
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
1 avril 2020 à 12:37
qu'as-tu lu comme documentation à propos de "
use index
"?

évidement que les insert remettent les index à jour. as-tu lu et compris ce que faisait
ANALYZE TABLE
?

dans quel contexte fais-tu ce travail?
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
1 avril 2020 à 13:30
>qu'as-tu lu comme documentation à propos de "use index"?
Les indexes c'est simple mais complexe!
Ca aide le moteur de recherche pour otimiser ces recherche.
Il choisi normalement lui-même le meilleur index, mais il se trompe parfois
(on on s'y prend mal)
pour contourner on peux use index...
mais c'est pas si simple...


>as-tu lu et compris ce que faisait ANALYZE TABLE?
Pas à fond, mais à prioris j'ai lu que ca ne sert pas sur innoDB

>dans quel contexte fais-tu ce travail?
Pro. des page web (local) de supervision processus industrielle.

Mais je suis un peu pris par le temps et vais probablement faire l'impasse sur cette optimisation...
(sauf soluc rapide... je vais essayer un index timestamp par mois...)

Merci
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
1 avril 2020 à 14:15
tu fais ce travail dans le contexte d'une formation?
alors je pense utile que tu prennes le temps de lire et de comprendre, sinon l'exercice ne sert à rien.
quelle documentation utilises-tu?
0
Calimero90 Messages postés 17 Date d'inscription vendredi 18 octobre 2013 Statut Membre Dernière intervention 22 décembre 2021
1 avril 2020 à 14:35
> tu fais ce travail dans le contexte d'une formation?
NON, du tout. Je bosse à fond là !

> alors je pense utile que tu prennes le temps de lire et de comprendre, sinon l'exercice ne sert à rien.
C'est pas un exo. Lire et comprendre, oui, mais il faut des sousous du patron !

quelle documentation utilises-tu?
Google principalement.

Temp pis pour l'optimisation.
Merci encore.
0
yg_be Messages postés 22692 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 16 avril 2024 1 471
1 avril 2020 à 15:30
0