Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1701 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

[MySQL] temps fetching trop important

n°2330631
matheo265
Posté le 21-03-2019 à 08:02:27  profilanswer
 

Reprise du message précédent :
Oui, j'utilise les transactions car mon script d'insertion des données machines concerne plusieurs tables.
Pour MariaDB tu as vu juste ^^ Mais je débute et je ne sais pas encore ce que ça vaut.

mood
Publicité
Posté le 21-03-2019 à 08:02:27  profilanswer
 

n°2330670
matheo265
Posté le 21-03-2019 à 12:31:08  profilanswer
 

Salut,
 
J'ai réfléchi un peu à vos idées et conseils et voilà ce à quoi j'ai travaillé :
 
https://image.noelshack.com/fichiers/2019/12/4/1553167628-mld.jpg
 
Déjà j'ai réparti les champs dans plusieurs tables en fonction de leur contenu. Ensuite j'ai fait pointer un lien depuis ma table de données. Puis je modifierai mon script pour que à chaque retour machine il vérifie, pour chaque table, si les données précédentes sont identiques. Si oui : il insère un lien vers la dernière ligne, si non : il en créé une nouvelle dans la table correspondante.
 
Je sais pas si c'est très clair mes explications :D  
 
Et histoire de lier l'utile à l'agréable, un coup de partitionnement sur ces différentes tables (surtout "machinevalues" ).
 
Qu'en pensez-vous ?


Message édité par matheo265 le 21-03-2019 à 12:32:27
n°2330674
rufo
Pas me confondre avec Lycos!
Posté le 21-03-2019 à 13:15:42  profilanswer
 

C'est pas forcément un souci. Je développe moi aussi des scripts d'insertion de données sur plusieurs tables, sans pour autant passer par les transactions. Ca complique juste un peu les scripts mais rien de bien méchant ;)
 
J'avais testé MariaDB pour l'une de mes applis en signature pour voir si j'avais des gains de perfs par rapport à MyIsam, mais dans mon cas, je n'ai rien vu de particulier. Du coup, je suis resté en MyIsam.

n°2330675
rufo
Pas me confondre avec Lycos!
Posté le 21-03-2019 à 13:19:33  profilanswer
 

Bof, pas convaincu. Sur les perfs, ça va peut-être amélioré mais t'as toujours le pb de non évolutivité. Si tu ajoutes une nouvelle caractéristique, tu dois modifier ton MCD et ton code.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2330676
matheo265
Posté le 21-03-2019 à 14:44:47  profilanswer
 

L'autre solution serait de passer dans une table du style
 
id_caracteristique,id_machine,timestamp,valeur
 
Mais ça va terriblement me compliquer la vie quand je voudrais composer les rapports en colonnes et non en lignes...

n°2330682
rufo
Pas me confondre avec Lycos!
Posté le 21-03-2019 à 16:12:54  profilanswer
 

C'est la table que je t'avais proposée, où, pour être précis, il te faut 2 tables :
- une qui contient le nom des caractéristiques avec un id et un libellé
- l'autre qui a la forme que tu as donnée qui correspond à la table que j'avais appelée valeurscaractéristiques.
 
Oui, pour les rapport, ça sera un peu plus compliqué à produire. Il faudra passer par le langage de dév utilisé pour codé l'appli pour passer d'un format lignes à un format colonnes. Mais c'est pas cher payé pour augmenter significativement tes perfs de fonctionnement et l'évolutivité de l'appli. Ainsi, si t'as besoin de rajouter un ou plusieurs paramètres, ça va se faire juste par de la conf et non du dév. ;)
Tu peux aussi ajouter un champ "type_valeur" qui indiquera si la valeur est un int, un float ou un string.
Tu peux même aller plus loin en rajoutant 3 tables de stockage des valeurs : une table pour les valeurs de type int, un pour les floats et une pour les strings.
 
Du coup ta table valeurscaracteristiques devient :
id_caracteristique,id_machine,timestamp,type_valeur,id_valeur
id_valeur pointera sur l'une des 3 tables en fonction de la valeur de type_valeur
 
Autre solution, plus simple :
ta table valeurscaracteristiques devient :
id_caracteristique,id_machine,timestamp,type_valeur,val_int,val_float,val_string
Il n'y aura qu'une seul des 3 champs renseignés à chaque fois. Du coup, on peut peut-être se passer du champ "type_valeur"; à voir...
Pour retourner la valeur d'une caractéristique, tu pourras passer par COALESCE(val_int,val_float,val_string) AS Valeur


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2330690
matheo265
Posté le 21-03-2019 à 16:39:31  profilanswer
 

Attends un instant, je vais me chercher une corde... ^^

n°2330693
rufo
Pas me confondre avec Lycos!
Posté le 21-03-2019 à 16:46:46  profilanswer
 

Ben si t'as qu'un champ "valeur", faudra que tu stockes tout en string. Du coup, pour faire des aggrégations, tu vas galérer. Tu seras sans doute obliger de faire des cast(), ce qui risque de pas être top au niveau des perfs.
Ma dernier solution évite ce problème. ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2330696
matheo265
Posté le 21-03-2019 à 16:51:42  profilanswer
 

Je vais essayer d'étudier ça. Comprendre dans un premier temps, expérimenter dans un second :)

n°2330700
rufo
Pas me confondre avec Lycos!
Posté le 21-03-2019 à 17:00:30  profilanswer
 

Tu peux étudier le MCD de mon appli Icare, disponible dans ma signature, si tu veux. C'est le même principe mais je n'ai pas eu à faire 3 champs pour stocker la valeur car je ne faisais pas de stats sur les attributs gérés en conf.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
mood
Publicité
Posté le 21-03-2019 à 17:00:30  profilanswer
 

n°2331004
el muchach​o
Comfortably Numb
Posté le 28-03-2019 à 11:47:41  profilanswer
 

matheo265 a écrit :

La table fait actuellement...

Spoiler :

4,7 Go pour 6 550 335 lignes...


C'est une flotte d'entreprise et le j'ai une ligne de données par seconde (le client ne souhaite pas transiger sur ce point)...

 

J'ai fait un EXPLAIN et RAS, j'ai bien créé les bons index. Maintenant je m'attarde du côté de Mysqltuner puis je regarderai aussi les table memory.


Cette modélisation est catastrophique et le nombre de lignes va exploser. Les données sont ultra dupliquées, ce qui fait que ta base est inutilement grosse et lourde. Par ex il faut séparer les données qui ne changent pas (dans des tables séparées) de celles qui changent, et séparer les échelles de temps: tu n'as pas besoin de la pression des pneus ou de l'essence toutes les secondes, je pense, tu peux probablement t'en contenter toutes les 10 mn.

 

Et ça ne fera qu'empirer avec l'augmentation du nombre de véhicules.

 

Il faut absolument que tu refasses un modèle correctement modélisé.


Message édité par el muchacho le 28-03-2019 à 11:56:39

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
n°2331006
matheo265
Posté le 28-03-2019 à 12:00:15  profilanswer
 

Merci el muchacho d'avoir enlevé la "modélisation intelligente" ;) On fait tous comme on peut...
 
Pour répondre à ta remarque qui fait écho à celle de rufo et de mechkurt, j'ai bien conscience de ces problèmes et je vais voir ce que je peux faire dès que j'aurais du temps.
 
Pour les remontées je ne suis pas décideur et c'est le client qui aura le dernier mot. Et malheureusement il ne désire pas trop transiger malgré mes arguments... A moi donc de trouver d'autres méthodes en m'inspirant des idées de ce post.


Message édité par matheo265 le 28-03-2019 à 12:03:52
n°2393971
depart
Posté le 24-08-2021 à 14:52:23  profilanswer
 

Je réutilise ce post pour essayer de partager une expérience un peu étrange.
Je suis en train d'optimiser une table qui est en gros un agenda pour plusieurs personnes.
 
J'ai une requête pour récupérer le planning d'une personne que je trouvais un peu lente (autour de 100ms sur un petit kimsufi).
J'ai viré des bouts petits à petit pour voir d'où pouvait venir le souci et j'aboutis au constat suivant :
 
sur un champ datetime (not null), lorsque je fais un where date > xyz c'est vachement plus lent que < xyz... et ce même si le < ramène  
 
Exemple en ayant dégagé un max de choses :
 
SELECT rdv_id, date, date_fin, ...
FROM rdv WHERE date > '2021-08-24'  
975 enregistrements en 480ms
 
SELECT rdv_id, date, date_fin, ...
FROM rdv WHERE date < '2021-08-24'  
71168 enregistrements en 8.6ms
 
Ca c'est sans index.
Si je rajoute un index sur la colonne date, ça va mieux... mais dès que je rajoute mes autres clauses dans le where c'est de nouveau super lent sur le ">"
 
j'ai essayé une multitude d'index, index sur plusieurs colonnes... globalement ça ne change rien.
 
WTF ???
 
Mysql 8.0.26, tables innoDB


Message édité par depart le 24-08-2021 à 15:24:12
n°2393974
rufo
Pas me confondre avec Lycos!
Posté le 24-08-2021 à 15:09:20  profilanswer
 

si tu convertis (dans la requête sql) date et la valeur en timestamp et que tu fais la même opération, il se passe quoi ?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2393976
depart
Posté le 24-08-2021 à 15:16:09  profilanswer
 

rufo a écrit :

si tu convertis (dans la requête sql) date et la valeur en timestamp et que tu fais la même opération, il se passe quoi ?


pas mieux (pire)
 
En gros la requête finale c'est à peu près ça  (j'ai aussi des jointures sur d'autres tables mais les rajouts de temps sont marginaux) :

SELECT rdv_id, date, date_fin
FROM rdv WHERE user_id = 279
AND location_id = 279
AND
(
 (UNIX_TIMESTAMP(date) >= UNIX_TIMESTAMP('2021-08-21') AND UNIX_TIMESTAMP(date) <= UNIX_TIMESTAMP('2021-08-31'))
        OR
        (UNIX_TIMESTAMP(date) <= UNIX_TIMESTAMP('2021-08-21') AND UNIX_TIMESTAMP(date_fin) >= UNIX_TIMESTAMP('2021-08-21'))
)


 
J'ai tenté aussi des UNION au lieu du OR sur les plages de date pour optimiser en théorie... mais en pratique c'est pas mieux.
 
Voilà, ça :

SELECT rdv_id, date, date_fin
FROM rdv WHERE user_id = 279
AND location_id = 279
AND
(
  (date >= '2021-08-21' AND date <= '2021-08-31')
  OR
         (date <= '2021-08-21' AND date_fin >= '2021-08-21')
)


--> 100 ms pour ce truc basique (table de 70 000 lignes)
 
Si à l'arrache je remplace les > par des < (bien sûr les résultats ne sont pas ce dont j'ai besoin, mais ça retourne vachement plus de lignes au passage)  

SELECT rdv_id, date, date_fin
FROM rdv WHERE user_id = 279
AND location_id = 279
AND
(
  (date <= '2021-08-21' AND date <= '2021-08-31')
  OR
         (date <= '2021-08-21' AND date_fin <= '2021-08-21')
)


--> 8 ms (pour 4600 lignes retournées au lieu de 14)


Message édité par depart le 24-08-2021 à 15:24:39
n°2393978
depart
Posté le 24-08-2021 à 16:16:01  profilanswer
 

Bon... j'ai créé un index sur mes 4 champs (user_id,location_id, date, date_fin) ça n'a rien changé. Il n'était pas utilisé à priori (constaté via EXPLAIN).
 
du coup j'ai tenté de forcer l'usage de l'index :
SELECT...
FROM rdv USE INDEX(nom_de_l_index)
WHERE...
 
Et là ça fonctionne. Je passe donc de 100 ms à environ 18ms pour ma requête finale, ce qui est nettement plus correct.
Je n'aime pas trop corréler la requête SQL dans mon code PHP et les index (trop peur de zapper un jour leur création, de les renommer...) mais c'est ce qui semble le plus efficace pour l'instant.
 
Pourquoi donc mysql n'utilise pas l'index créé spécialement sur les 4 champs de la clause where ?

n°2394244
depart
Posté le 28-08-2021 à 14:40:20  profilanswer
 

Bon je reviens sur mes problèmes de performances mySQL. Je pensais en être sorti (pour rappel, donc comme indiqué juste au dessus : forçage de l'utilisation d'un index sur 4 colonnes, qui n'est pas utilisé autrement).
 
En fait sur mes données de test ça semblait ok, mais j'ai un cas (un utilisateur) avec pas mal de de données (rendez-vous dans une table d'agenda) et ça part grave en cacahuète : 600ms pour récupérer entre 0 et 20 rdv dans une table de 70 000 lignes dont 20 000 appartiennent à cette personne !
 
Le truc qui me fait halluciner c'est que quand je fais la requête dans PHPMyAdmin le temps de réponse est plutôt correct (80ms, c'est un poil lent mais quand même pas cata), mais quand je fais la requête depuis la page PHP (via PDO), le temps explose.
J'ai tenté de récupérer le EXPLAIN correspondant à la même requête (via PHP/PDO) et il a l'air identique à celui via PHPMyAdmin...
 
Là je sèche, comment je pourrais débugger ça ?


Message édité par depart le 28-08-2021 à 15:37:38
n°2394271
depart
Posté le 29-08-2021 à 08:53:10  profilanswer
 

Eh ben quel m**dier !!!
Il s'avère que selon les données, mySQL va optimiser différemment l'utilisation des index & co, et au final ça peut donner des résultats plus pourris que d'autres !
 
J'ai resplitté ma requête "OR" en 2 SELECT avec UNION
 
Donc pour rappel, en partant de ça :

SELECT rdv_id, date, date_fin
FROM rdv
WHERE user_id = 279
AND location_id = 279
AND
(
  (date >= '2021-08-21' AND date <= '2021-08-31')
  OR
         (date <= '2021-08-21' AND date_fin >= '2021-08-21')
)


 
Ca donne quelque chose comme :

SELECT rdv_id, date, date_fin
FROM rdv
WHERE user_id = 279
AND location_id = 279
AND date >= '2021-08-21' AND date <= '2021-08-31'
UNION  
SELECT rdv_id, date, date_fin
FROM rdv WHERE user_id = 279
AND location_id = 279
AND date <= '2021-08-21' AND date_fin >= '2021-08-21'


 
Là j'ai constaté que selon l'utilisateur ça n'utilisait pas les mêmes INDEX, et en forçant les plus logiques (l'index sur les 4 colonnes : user_id, location_id, date, date_fin) ça donnait des bons résultats pour un utilisateur mais des mauvais pour un autre...
Au final ce qui semble fonctionner pour tout le monde c'est :
 

SELECT rdv_id, date, date_fin
FROM rdv USE INDEX(index_sur_les_4_colonnes)
WHERE user_id = 279
AND location_id = 279
AND date >= '2021-08-21' AND date <= '2021-08-31'
UNION  
SELECT rdv_id, date, date_fin
FROM rdv USE INDEX(index_sur_date_fin)
WHERE user_id = 279
AND location_id = 279
AND date <= '2021-08-21' AND date_fin >= '2021-08-21'


 
Bon ben j'aurai appris pas mal de choses sur les index, notamment que :
- mySQL peut être totalement à côté de la plaque pour l'optimisation des requêtes même sur des choses simples
- ce qui nous semble logique n'est pas forcément le plus efficace, par exemple réutiliser "index_sur_les_4_colonnes" sur la 2è partie de la requête (après le UNION) donne des résultats moins bons que juste la date de fin !!!


Message édité par depart le 30-08-2021 à 15:09:01
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
[MySQL] Plusieurs tables ou une seule grosse dans ce cas?[Python] Tableaux qui s'actualisent en même temps
Changement de logo selon le tempsOut of memory - sql Oracle/php
Projet de stage php/mysql[MySQL] Supprimer toutes les contraintes d'une table
securiser l'acces à la base mysqlMySQL Conflit Xampp / Wamp
[MySQL] Combiner un select classique et un count()[MySQL] Ajout de multiples enregistrements avec trigger
Plus de sujets relatifs à : [MySQL] temps fetching trop important


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR