Pourquoi MySQL/innoDB n'utilise pas mon bel index à partir de ???
Calimero90
Messages postés
49
Date d'inscription
Statut
Membre
Dernière intervention
-
yg_be Messages postés 23541 Date d'inscription Statut Contributeur Dernière intervention -
yg_be Messages postés 23541 Date d'inscription Statut Contributeur Dernière intervention -
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...
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...
A voir également:
- Exolire
- Creer un groupe whatsapp a partir d'un autre groupe - Guide
- Index téléphonique - Guide
- Comment savoir si quelqu'un utilise mon adresse ip - Guide
- Comment faire une recherche à partir d'une photo - Guide
- Salut j'utilise whatsapp - Accueil - Messagerie instantanée
8 réponses
yg_be
Messages postés
23541
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 584
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)?
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)?
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
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
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.
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.
.
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)
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
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
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Bin comme ça :
Bon ok, je remplace super rapide par relativement rapide, mais quand même...
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...
>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
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
>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
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
> 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.
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.