IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut [WD26] Ralentissement des autres utilisateurs pendant l'exécution d'une requête (Serveur OVH avec HFSQL C/S)
    Bonsoir,

    J'ouvre cette discussion car j'ai un problème de ralentissement lors de l'exécution et la récupération des données d'une requête sur le serveur.

    Nous avons notre propre serveur OVH, avec HFSQL C/S.

    Je bosse sur une CRM et une fonctionnalité permet de rechercher une liste de contact selon un critère choisi par l'utilisateur. La liste de contact s'affiche dans une table où j'affiche quelques données de base des contacts (Nom, prénom etc.), le numéro de téléphone fixe par défaut, le numéro de mobile par défaut, l'email par défaut et la société.

    Les données de base se trouvent dans la table Contact.
    Les données téléphone fixe, téléphone mobile et email se trouve dans une table Contact_Communication.

    La table Contact_Communication est construite de la façon suivante :
    CTCOMid : Clé primaire table Contact_Communication
    CNTid : Clé étrangère de la table Contact.
    MDCcode : Entier et clé avec doublon -> code du support de communication (1 = téléphone fixe, 2 = téléphone mobile, 3 = email)
    CTCOMcodePays : Chaine, code du pays pour les numéros de téléphone.
    CTCOMvaleur : Chaine. Valeur selon le support de communication choisi. (Le numéro de téléphone, l'email...)
    CTCOMdefaut : Booléen et clé avec doublon -> 1 défaut par code support de communication par contact. (Donc chaque contact peut avoir un tél fixe, un tél mobile et un e-mail par défaut maximum.)


    Je récupère donc les données de base du contact (table contact) et le téléphone fixe, téléphone mobile et email par défaut des contacts (Chacun étant présent dans la table Contact_Communication) via l'unique requête suivante :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT Contact.CONTid, Contact.CONTcode, Contact.CONTcodeInt, Contact.CONTnom, Contact.CONTprenom, Contact.SOCid, Societe.SOCnom, TelFixe.CTCOMcodePays AS TelFixeCodePays, TelFixe.CTCOMvaleur AS TelFixeValeur, TelMobile.CTCOMcodePays AS TelMobileCodePays, TelMobile.CTCOMvaleur AS TelMobileValeur, Email.CTCOMvaleur AS EmailValeur
    FROM CONTACT 
    LEFT OUTER JOIN Societe ON Contact.SOCid = Societe.SOCid
    LEFT OUTER JOIN Contact_Communication AS TelFixe ON Contact.CONTid = TelFixe.CONTid AND TelFixe.MDCcode = 1 AND TelFixe.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS TelMobile ON Contact.CONTid = TelMobile.CONTid AND TelMobile.MDCcode = 2 AND TelMobile.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS Email ON Contact.CONTid = Email.CONTid AND Email.MDCcode = 3 AND Email.MDCdefaut = 1

    La requête possède une triple jointure avec alias sur la table Contact_Communication afin de récupérer le téléphone fixe par défaut, le téléphone mobile par défaut et l'email par défaut en une seule ligne afin de les afficher chacun dans une colonne distincte de ma table des résultats de la recherche.

    La requête fonctionne et est assez rapide. Pour 50 000 contacts, avec chacun un téléphone fixe, téléphone mobile et email par défaut (Donc 150 000 lignes dans la table Contact_communication) la durée de la requête ne dépasse pas 15 secondes.


    Le vrai problème c'est que lorsque j'exécute la requête (sur les 50k contacts pour l'exemple) qui prend une quinzaine de seconde, les autres requêtes des autres utilisateurs sont ralenties, toutes bases confondues sur le serveur HFSQL CS OVH. C'est à dire que si un autre utilisateur exécute la même requête pendant que la mienne est en cours, même sur une base différente (mais du même serveur HFSQL CS), la sienne prends une dizaine de seconde de plus, les autres requêtes étant également impactées, tant que les requêtes de 15 secondes ne sont pas terminées. Une fois celles-ci terminées, plus de soucis de ralentissement.


    Je ne sais pas d'où vient le problème, ma requête n'est peut-être pas la plus optimisée du monde, mais au point de faire ralentir les requêtes des autres utilisateurs, ça me parait excessif non ? C'est comme-ci le réseau était saturé pendant la récupération des données et du coup tous les autres requêtes sur le serveur, même sur des bases différentes, sont impactées.


    Auriez-vous des pistes d'où pourrait venir le problème ?

    La triple jointure de ma requête SQL sur la même table ? Au point de ralentir tout le serveur ? (Les rubriques CONTid, MDCcode et CTCOMdefaut de ma table Contact_Communication sont toutes en clés avec doublon, j'ai également créé une clé composé CONTid + MDCcode + CTCOMdefaut afin d'optimiser les jointures de la requête SQL mais je ne sais pas si elle est réellement utilisée...)
    Ou le problème viendrait du serveur ? Ou autre ?


    Merci d'avance...

    Bonne soirée,

    Djsven

  2. #2
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    Ta requête est correcte... rien à dire. La clé étrangère cntId, liée à ContId doit faire le job pour aider à trouver les éléments enfants dans la table Contact_Communication.
    Mais 15 secondes pour récupérer 50000 lignes x 10 colonnes venant de 4 tables, c'est très long.
    Bon, je relativise.
    Si tu fais
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT count(*) , count( TelFixe.CTCOMvaleur ) as nbFixe, count(TelMobile.CTCOMvaleur) as nbMobile
    FROM CONTACT 
    LEFT OUTER JOIN Societe ON Contact.SOCid = Societe.SOCid
    LEFT OUTER JOIN Contact_Communication AS TelFixe ON Contact.CONTid = TelFixe.CONTid AND TelFixe.MDCcode = 1 AND TelFixe.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS TelMobile ON Contact.CONTid = TelMobile.CONTid AND TelMobile.MDCcode = 2 AND TelMobile.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS Email ON Contact.CONTid = Email.CONTid AND Email.MDCcode = 3 AND Email.MDCdefaut = 1
    Ca donne quoi ?
    En terme de requête, le moteur va faire à peu près la même chose.
    Mais en terme de réseau, il va te renvoyer une seule ligne, et pas 50000.
    L'idée est de voir comment se répartissent les 15 secondes. Est-ce que c'est 15 secondes pour exécuter la requête, et rien du tout pour transférer les données, ou l'inverse.

    Mais derrière, quelles actions faire ?
    hReindexe() ... ça te parle ? cf aide
    Est-ce que la base est bien administrée ? Est-ce que la commande hReindexe est lancée de temps en temps pour maintenir les performances à un niveau correct ?
    Avec HFSQL CS, vous pouvez mettre en place une réindexation automatique.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    Bonjour,

    Et encore les ~15 secondes c'est sur notre futur serveur de production, sur une base que j'ai créé spécialement pour tester, donc juste avec les 50k contacts et les 150k contact_communication associés aux 50k contacts. Sur notre serveur de test, moins performant que le production, la requête prend 25 secondes...

    J'ai testé ta requête à la fois sur notre serveur de test et notre futur serveur de production. J'ai également utilisé la commande hReindexe() sur la table Contact, la table Contact_Communication et la table Societe utilisées dans la requête (Même si HVérifieIndex me disait que les index étaient ok sur ces trois tables). Voici les résultats :

    Serveur OVH de production :
    - Avant hReindexe() : Requête standard avec récupération des 50000 lignes x 10 colonnes : 12 secondes 56
    - Avant hReindexe() : Ta requête count avec récupération d'une seule ligne : 12 secondes 36
    - Après hReindexe() : Requête standard avec récupération des 50000 lignes x 10 colonnes : 12 secondes 30
    - Après hReindexe() : Ta requête count avec récupération d'une seule ligne : 12 secondes 25

    Serveur OVH de test (moins performant que le prod) :
    - Avant hReindexe() : Requête standard avec récupération des 50000 lignes x 10 colonnes : 27 secondes 87
    - Avant hReindexe() : Ta requête count avec récupération d'une seule ligne : 23 secondes
    - Après hReindexe() : Requête standard avec récupération des 50000 lignes x 10 colonnes : 23 secondes 8
    - Après hReindexe() : Ta requête count avec récupération d'une seule ligne : 22 secondes 68


    J'ai également essayé de supprimer une jointure sur la table Contact_Communication, pour tester simplement, et j'obtiens 8.83 secondes (serveur production) au lieu de 12 secondes 56 avec les 3 jointures. Et avec une seule jointure sur la table Contact_Communication j'obtiens 5.7 secondes.

    De même si la requête ne trouve que 1000 enregistrements par exemple (au lieu des 50k) après application d'une condition supplémentaire sur la requête, la durée passe de 12.56s à une seconde.



    Pour tes dernières questions :
    - Non la commande hReindexe() n'est pas utilisée pour le moment même si j'ajouterais une fonctionnalité pour réindexer toutes les tables. Mais la base que j'ai créé sur le serveur de production pour le test date d'hier, et pourtant j'obtiens quand même 12s56 pour les 50k. Et après utilisation de la commande hReindexe() sur les 3 tables utilisées pour la requête sur la base du serveur de test (où j'obtiens 23 secondes pour les 50k) et la base production, il n'y a pas de réelles différences...

    C'est vrai que la durée de récupération est longue pour simplement 50k contacts, mais ce qui m'inquiète encore plus c'est que pendant la durée d'exécution de la requête, si d'autres utilisateurs exécutent des requêtes sur ce même serveur (même si ce n'est pas la même base), ces dernières sont ralenties et prennent plus de temps.


    Je sèche un peu là, je peux éventuellement utiliser la commande hReindexe() sur toutes les tables (plus d'une centaine) au lieu des 3 utilisées pour la requête, mais je ne suis pas sur que ça change grand chose, surtout que la base sur le serveur prod est nouvelle et à part ces 3 tables, les autres n'ont pas de données.
    Edit : J'ai effectué un hReindexe sur l'ensemble des fichiers, ça n'a pas résolu le problème.



    Djsven

  4. #4
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    La requête avec Count() est aussi long, donc ce n'est pas l'acheminement des données du serveur vers le client qui est long.

    Dans ton premier message, tu dis que CONTid est une clé étrangère.
    On est bien d'accord que cette clé relie CONTACT avec CONTACT_COMMUNICATION ?

    Tu ne parles pas de la clé SOCId ?
    C'est un oubli, ou bien c'est parce que SOCId n'est pas déclarée comme clé étrangère (ou clé autre ...) ?

    Pour tester, ça donne quoi avec cette requête :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT count(*) , count( TelFixe.CTCOMvaleur ) as nbFixe, count(TelMobile.CTCOMvaleur) as nbMobile
    FROM CONTACT 
    LEFT OUTER JOIN Contact_Communication AS TelFixe ON Contact.CONTid = TelFixe.CONTid AND TelFixe.MDCcode = 1 AND TelFixe.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS TelMobile ON Contact.CONTid = TelMobile.CONTid AND TelMobile.MDCcode = 2 AND TelMobile.MDCdefaut = 1
    LEFT OUTER JOIN Contact_Communication AS Email ON Contact.CONTid = Email.CONTid AND Email.MDCcode = 3 AND Email.MDCdefaut = 1

    J'ai supprimé la table SOCIETE.
    Si d'un coup, ça devient rapide, c'est que le moteur galère pour aller trouver les infos voulues dans SOCIETE. Et donc que la clé SOCId manque ?

    Je reste vraiment sur la piste que 15 secondes pour cette requête, c'est trop long. Si cette requête passe de 15 secondes à 1 seconde, ça résout les 2 problèmes.

    Et hReindexe sur toutes les tables ne changerait rien...
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    Oui Contact.CONTid (clé primaire de la table Contact) relie bien Contact_Communication

    La clé SOCid dans la table Contact est bien la clé étrangère de la table Société. Je l'utilise dans la requête pour faire la jointure avec la table Société pour afficher le nom de la société du contact s'il en fait parti d'une.

    Je viens d'essayer ta requête, sans la jointure de la table société, sur le serveur de production et j'obtiens 10.5 secondes. (contre 12.5 secondes avec cette jointure)


    J'ai essayé sans aucune jointure, j'obtiens 28ms pour récupérer les 50k contacts. Avec la jointure société uniquement, ça passe à 2 secondes, en ajoutant en plus une jointure Contact_Communication 5.7 secondes, deux jointures Contact_Communication 8.83 secondes et les trois jointures Contact_Communication 12.5 secondes

  6. #6
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    28ms pour lire la table contact. C'est rapide, c'est encourageant. Le disque est suffisamment rapide. Et donc les délais dès qu'on fait des jointures, c'est parce que ce p*** de machin part dans des recherches tordues pour aller accéder aux tables reliées.

    Je pratique peu les clés étrangères.
    Sur un cas comme ça, j'aurais un index sur la table contact_communication : clé composée : MDCdefaut+CONTid+MDCcode, a priori dans cet ordre.
    Et un truc similaire pour la table SOCIETE.
    Je pense qu'il n'y a pas de contre-indication à avoir une clé étrangère, plus cette clé composée.

    La clé étrangère sert aux contrôles d'intégrité : pour chaque ligne dans CONTACT_COMMUNICATION, elle sait aller vérifier très vite ce qu'il y a dans CONTACT.
    Mais dans l'autre sens, pour chaque ligne de CONTACT, aller voir ce qu'il y a dans CONTACT_COMMUNICATION, ce n'est pas son job, elle ne sait pas faire ça efficacement.
    J'ajouterais donc la clé composée, comme dit plus haut.
    Avec cette clé, le système va savoir trouver très vite un enregistrement cherché dans CONTACT_COMMUNICATION

    Et c'est ce qu'on veut ici : le système lit ligne à ligne la table CONTACT, et pour chaque ligne, il a besoin de trouver ce qui correspond dans CONTACT_COMMUNICATION

    Je propose MDCdefaut+CONTid+MDCcode , mais MDCdefaut+CONTid , ou bien CONTid+MDCcode , ou bien CONTid tout seul, ça va faire le job tout aussi bien. C'est en voyant les autres besoins que tu sauras choisir quelle combinaison est la mieux.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    Oui je suis d'accord, mais le problème c'est que c'est déjà ce que j'ai fait dans la table Contact_Communication :
    j'ai également créé une clé composé CONTid + MDCcode + MDCdefaut afin d'optimiser les jointures de la requête SQL mais je ne sais pas si elle est réellement utilisée...)
    A part que j'avais choisi l'ordre suivant : CONTid + MDCcode + MDCdefaut plutôt que MDCdefaut+CONTid+MDCcode comme tu me conseilles car j'ai repris l'ordre de mon LEFT OUTER JOIN
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    LEFT OUTER JOIN Contact_Communication AS TelFixe ON Contact.CONTid = TelFixe.CONTid AND TelFixe.MDCcode = 1 AND TelFixe.MDCdefaut = 1
    c'est à dire CONTid puis MDCcode puis MDCdefaut. Je ne savais pas si l'ordre devait correspondre ou non au LEFT OUTER JOIN ou si ça n'avait pas de rapport.


    28ms pour lire la table contact
    28ms pour la requête Count sans jointure, 500ms avec la requête standard sans les jointure et la récupération des 50k contacts avec les données de base (hors société, tél fixe défaut, tél mobile défaut et email défaut du coup)

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 199
    Points : 12 775
    Points
    12 775
    Par défaut
    Bonjour,
    Si je peux apporter mon grain de sel...

    Lors de la création d'un index composé, il faut privilégier en premier la colonne la plus restrictive. Donc ici je privilégierai CONTid+MDCcode, d'autant plus que la première colonne est (à priori) de type integer.

    Je vois également un "potentiel" problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ...TelMobile.MDCcode = 2 AND TelMobile.MDCdefaut = 1
    Si je traduis bien le nom des colonnes, il s'agit ici de chaines, mais la valeur à tester n'est pas entre guillemet. Ca impose au moteur de faire une conversion avant de faire la comparaison, et du coup il y a de forte chance que l'index ne sera plus éligible.

    Tatayo.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    J'ai bien une clé composée CONTid+MDCcode+MDCdefaut (De la colonne la plus restrictive à la moins du coup) mais j'ai également deux autres clés composées dans cette table que j'utilise pour faire des HlitRecherchePremier classique dans mon appli, est-ce que cela pourrait poser problème d'avoir plusieurs clés composées ? J'en ai une sur 5 rubriques qui me sert à vérifier un éventuel doublon avant un nouvel ajout. Je pourrais éventuellement supprimer cette clé et exécuter une requête SQL pour vérifier les doublons si cela peut poser problème.

    Voici la table complète :
    Nom : 2021-12-07_15h14_30.png
Affichages : 152
Taille : 26,5 Ko


    Non MDCcode est un entier, et MDCdefaut un booléen. J'ai tout de même essayé avec les guillemets mais ça n'a pas changé la durée

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 199
    Points : 12 775
    Points
    12 775
    Par défaut
    La présence de plusieurs clés composées ne pose aucun problème de performance lors de recherche, "au pire" le moteur ne va pas prendre la bonne.
    L'impact sera surtout sur les mises à jour, puisque le moteur dois maintenir ces indexes à jour.

    Tatayo.

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    "au pire" le moteur ne va pas prendre la bonne.
    Dans le cas où le moteur ne prendrait pas la bonne lors de l'exécution de la requête, cela ne pourrait pas venir de là ?



    Edit : Je viens également d'essayer en local en hfsql classique, la même requête sur 50k contacts, et cela met 13 secondes. Etonnant que la durée soit similaire en local que sur un serveur dédié distant en HFSQL C/S non?

  12. #12
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    Tatayo dit : au pire, le moteur ne va pas prendre la bonne clé.
    Oui, mais si le moteur s'avise de prendre MDCDefaut, c'est un peu comme s'il n'utilisait pas de clé du tout.
    Ici, je pense que tu as trop de clés. Je n'aime pas toutes ces clés.

    ContId est inutile. Si tu as besoin de faire un accès en utilisant ContId, le moteur peut deviner d'utiliser ContId+CTCOMrgpd par exemple, et ça donnera les mêmes performances.
    La clé unique CTCOMId, ajoutée par HFSQL, je la supprimerais purement et simplement.

    Mais on est dans le brouillard.
    Comme tu disais dans le 1er message : j'ai également créé une clé composé CONTid + MDCcode + CTCOMdefaut afin d'optimiser les jointures de la requête SQL mais je ne sais pas si elle est réellement utilisée...)

    J'utilise beaucoup Oracle, à la place de HFSQL CS, et là, on peut vérifier quel est le plan d'exécution, quelles clés sont utilisées, et on peut même obliger le moteur à utiliser une clé précise. On pilote tout. Idem avec des outils comme PostgreSQL ou Maria DB ou ...
    Avec HFSQL CS, je ne sais pas trop, mais je ne crois pas qu'on ait des outils pour piloter tout ça.

    Ici, je préconiserais ce test :
    Tu dupliques le fichier CONTACT_COMMUNICATION en CONTACT_COMMUNICATION2 , avec son contenu.
    Tu supprimes toutes les clés, y compris les clés étrangères, et tu gardes uniquement CONTid+MDScode+MDCdefaut
    Tu t'assures que tout est bien avec un hVerifieIndex() ou quelque chose du genre.
    Et tu testes,en lisant ce nouveau fichier.
    Là, on est à peu près sûr que le système utilisera la clé qu'il faut. Soit le temps d'exécution diminue drastiquement , soit pas
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  13. #13
    Expert éminent
    Avatar de frenchsting
    Homme Profil pro
    multitâches-multifonctions
    Inscrit en
    Juin 2003
    Messages
    5 207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : multitâches-multifonctions
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 207
    Points : 9 208
    Points
    9 208
    Par défaut
    Bonjour,

    J'ai une idée mais je suis peut-être en dehors de la plaque vu que j'ai lu en diagonale.

    Tu as dis que ta requête sans jointure est très rapide. Ne peux tu pas la parcourir pour charger en mémoire les infos (en tableau associatif) et récupérer la clé étrangère. Puis tu fais des requêtes sur les 3 autres tables du type :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT rubrique FROM Table Where CleUnique in ([...])
    où la partie entre crochets correspond à la liste de tes clés uniques.

    Je me dis que l'exécution de plusieurs requêtes "simples" sont plus rapides qu'une requête "complexe".
    Commencez toujours appuyer sur la touche F1 et puis n'hésitez à passer par un moteur de recherche...
    Le forum est fait pour répondre aux questions : pas la peine de me les envoyer par MP. Merci.

    Sur internet, tout est vrai ! Honoré de Balzac
    Make it real not fantasy... Herman Rarebell

  14. #14
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    Pas du tout aligné avec toi Frenchsting.
    Le SGBD, il est conçu pour faire des jointures entre fichiers, c'est vraiment son job.
    Il m'arrive de faire des jointures entre 10 ou 20 fichiers avec des millions de lignes en entrée... je calcule des statistiques par département par exemple, je récupère mes 95 lignes en 2 secondes.
    Si je voulais récupérer mes données, et faire les calculs en mémoire ... c'est en heures qu'il faudrait compter.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    @tbc92

    Alors j'ai fait le test en dupliquant la table Contact_Communication et en définissant toutes les rubriques comme étant "Non clé", et en ne conservant que la clé composée CONTid + MDCcode + MDCdefaut. J'obtiens 10.8 secondes (contre 12.5 auparavant).

    Je me suis également amusé à faire les tests suivants :

    - Sans clé avec doublon, juste avec la clé composé CONTid + MDCcode + MDCdefaut (Ta proposition) : 10.8 secondes
    - Sans clé avec doublon, juste avec la clé composé CONTid + MDCcode : 10.5 secondes
    - Sans clés composées, mais en conservant toutes les rubriques clés avec doublon : 9.1 secondes
    - Sans clés composées, avec uniquement CONTid en clé : 9.1 secondes
    - Sans clés composées, avec CONTid, MDCcode et MDCdefaut en clé avec doublon : 9.1 secondes
    - Sans clés composées ni clés : X minutes (logique)

    On remarque que peu importe le nombre de clé avec doublon que j'utilise, le résultat reste le même. Il change uniquement lorsque j'utilise des clés composées. Plus il y a de clés composées et plus la durée est longue ! Ainsi :

    - 0 clé composée : 9.1 secondes
    - 1 clé composée (Avec ou sans autres clés classiques) : 10.8 secondes
    - 2 clés composées : 11.7 secondes
    - 3 clés composées : 12.5 secondes (qui correspond bien au résultat que j'avais avec ma table Contact_Communication et ses 3 clés composées)
    - 4 clés composées : 13.3 secondes

    L'utilisation de clés composées semble donc déjà ralentir la requête. Et sans clés composées, peu importe le nombre de clés avec doublon standard, la clé étrangère CONTid semble toujours être utilisée et permet d'obtenir 9.1 secondes. Je n'ai pas réussi à obtenir moins de 9.1 secondes.

    C'est assez gênant car cette clé composée CONTid + MDCcode + MDCdefaut est utilisée dans certains de mes traitements donc ça m'embête de l'enlever (Ou il faut que j'enlève tous les hlitrecherchepremier sur cette clé pour passer en requête...), mais il y a quand même plus d'une seconde et demi avec VS sans... N'en parlons pas de mes 2 autres clés composées qui augmente la durée de 3 secondes et demis


    Note : J'ai effectué un hReindexe() après chaque test.

  16. #16
    Expert éminent
    Avatar de frenchsting
    Homme Profil pro
    multitâches-multifonctions
    Inscrit en
    Juin 2003
    Messages
    5 207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : multitâches-multifonctions
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 207
    Points : 9 208
    Points
    9 208
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    Pas du tout aligné avec toi Frenchsting.
    Le SGBD, il est conçu pour faire des jointures entre fichiers, c'est vraiment son job.
    Il m'arrive de faire des jointures entre 10 ou 20 fichiers avec des millions de lignes en entrée... je calcule des statistiques par département par exemple, je récupère mes 95 lignes en 2 secondes.
    Si je voulais récupérer mes données, et faire les calculs en mémoire ... c'est en heures qu'il faudrait compter.
    Je suis bien conscient que la bdd doit savoir gérer les jointures sans souci. Ce n'est pas le cas de hfcs. Passé une jointure dans la requête, les perfs s'effondrent. C'est pour ça que je soumettais cette idée.
    Commencez toujours appuyer sur la touche F1 et puis n'hésitez à passer par un moteur de recherche...
    Le forum est fait pour répondre aux questions : pas la peine de me les envoyer par MP. Merci.

    Sur internet, tout est vrai ! Honoré de Balzac
    Make it real not fantasy... Herman Rarebell

  17. #17
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    Passé une jointure dans la requête, les perfs s'effondrent.
    Ahhhhhh !
    HFSQL CS est si mauvais ?
    Donc il faudrait oublier HFSQL CS et passer à un vrai SGBD ? C'est clair que toutes les interrogations depuis le début (est-ce que le programme utilise telle clé ou telle autre), on ne les aurait pas avec un vrai SGBD. Les outils de contrôle permettent de vérifier ça.
    Et basculer vers PostgreSQL ou un outil du genre, c'était la seule piste qui me restait pour avancer.

    Une idée quand même, à l'instant, par curiosité :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT Contact.CONTid, Contact.CONTcode, Contact.CONTcodeInt, Contact.CONTnom, Contact.CONTprenom, Contact.SOCid, Societe.SOCnom, 
    Min ( case when comm.MDCCode=1 then CTCOMcodePays  else null end  ) as TelFixeCodePays ,
    Min ( case when comm.MDCCode=1 then CTCOMvaleur      else null end  ) as TelFixeValeur,
    Min ( case when comm.MDCCode=2 then CTCOMcodePays  else null end  ) as TelMobileCodePays ,
    Min ( case when comm.MDCCode=2 then CTCOMvaleur      else null end  ) as TelMobileValeur,
    Min ( case when comm.MDCCode=3 then CTCOMvaleur      else null end  ) as EmailValeur
    FROM CONTACT 
    LEFT OUTER JOIN Societe ON Contact.SOCid = Societe.SOCid
    LEFT OUTER JOIN Contact_Communication AS Comm  ON Contact.CONTid = Comm.CONTid   AND Comm.MDCdefaut = 1
    group by Contact.CONTid, Contact.CONTcode, Contact.CONTcodeInt, Contact.CONTnom, Contact.CONTprenom, Contact.SOCid, Societe.SOCnom

    On descend à 3 tables au lieu de 5.
    Si le null est bien géré, cette requête va donner le résultat voulu. Plus rapidement, parce que 2 LEFT OUTER JOIN seulement au lieu de 4.
    Max au lieu de Min va donner exactement la même chose, et peut régler les problèmes liés au Null.

    Mais si ça marche, ça tient du miracle. C'est totalement anormal que la lecture de la table Contact se fasse aussi vite, et que ça se dégrade à ce point dès qu'on ajoute 2 jointures.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  18. #18
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2020
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2020
    Messages : 66
    Points : 35
    Points
    35
    Par défaut
    Je testais quelque chose de similaire, avec un seul LEFT OUTER JOIN sur la table Contact_Communication, en mixant la récupération de données et un peu de programmation derrière pour la mise en forme pour l'affichage dans ma table.

    Ta requête résolvait le problème de programmer la mise en forme grâce au CASE. J'ai testé, mise à part que j'ai du remplacer Min par Max (pas de valeur sinon) et ajouter un "AND Comm.MDCcode in (1,2,3)" dans le LEFT OUTER JOIN (car j'ai également MDCcode = 4 et 5 que je ne souhaite pas récupérer ici), ça fonctionne. Mais la durée est pratiquement similaire à la requête avec les 4 LEFT OUTER JOIN (à 500ms près). Quelque chose la fait ralentir, le case ?


    Finalement, la requête qui m'a donné le meilleur résultat est la suivante :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT Contact.CONTid, Contact.CONTcode, Contact.CONTcodeInt, Contact.CONTnom, Contact.CONTprenom, Contact.SOCid, Societe.SOCnom, Contact_Communication2.MDCcode AS MDCcode, Contact_Communication2.CTCOMvaleur AS CTCOMvaleur, Contact_Communication2.CTCOMcodePays AS CTCOMcodePays
    FROM CONTACT 
    LEFT OUTER JOIN Societe ON Contact.SOCid = Societe.SOCid
    LEFT OUTER JOIN Contact_Communication2 ON Contact.CONTid = Contact_Communication2.CONTid AND Contact_Communication2.MDCcode IN (1,2,3) AND Contact_Communication2.MDCdefaut = 1
    ORDER BY CONTid

    Alors forcément, je récupère jusqu'à 150k lignes (50k contact * 3 MDCcode par défaut max), et je dois ensuite parcourir la requête et mettre en forme la ligne que je vais ajouter à mon tableau pour n'avoir plus que 50k contacts avec le tél fixe, le tél mobile et l'email sur la même ligne mais c'est la solution qui m'a donné le meilleur résultat, même si c'est loin d'être la plus propre. (2 secondes de moins que la requête avec les case et 2.5 secondes de moins que la requête des 3 LEFT OUTER JOIN sur la même table.)

    Je vais également supprimer toutes les clés composées de la table, qui font ralentir la requête (même la CONTid+MDCcode+MDCdefaut, étonnement...). Je devrais pouvoir atteindre un peu moins de 8 secondes pour la requête.

    Par contre le problème des autres requêtes utilisateurs ralenties pendant que celle-ci (ou une autre requête longue aussi je suppose) est en cours est toujours présent. C'est plus ce problème qui me pose vraiment problème et je ne vois pas comment le résoudre. Mauvaise configuration du serveur ? Pas assez de mémoire sur le serveur ? Nous avons 16gb. Pas assez puissant ? Processeur Intel Xeon-D 1521 - 4c/8t 2.4Ghz/2.7Ghz. SSD NVME 500GB et 4x4 TB HDD Sata, un serveur dédié OVH.
    Par comparaison à notre serveur test (serveur VPS 1c 4gb ram 40gb SSD), la requête est 2x plus rapide sur le serveur production, ce qui est logique, mais je me demande si la rapidité pourrait être encore augmentée en prenant un meilleur serveur dédié. Le serveur de production sera susceptible d'héberger plusieurs BDD, la notre et celle de clients éventuels, donc il faut qu'il tienne le coup, et là voir qu'une seule requête semble ralentir toutes les autres tant qu'elle n'est pas terminée, ça me fait un peu peur... Comme si le serveur donnait la priorité au maximum pour exécuter la requête au détriment des autres.

  19. #19
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 066
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 066
    Points : 9 417
    Points
    9 417
    Par défaut
    En fait, à ce niveau de la réflexion, la question à se poser, c'est de savoir si HFSQL CS est adapté.

    Personnellement, je suis incapable de te dire si ton serveur est correctement dimensionné.

    Pour les performances de HFSQL CS, on lit tout et son contraire... je viens de regarder la comm de PCSoft : https://pcsoft.fr/pcsoft/temoignages/22/ J'avais en tête Système-U qui utilise beaucoup PCSoft, et qui a des bases de données énormes... mais sur cette communication 'publicitaire' , ils disent qu'ils utilisent SQLServer comme base de données.

    Tu as un conflit parce que le moteur n'est pas foutu de traiter cette requête en moins d'1 seconde.
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  20. #20
    Expert éminent
    Avatar de frenchsting
    Homme Profil pro
    multitâches-multifonctions
    Inscrit en
    Juin 2003
    Messages
    5 207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : multitâches-multifonctions
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 207
    Points : 9 208
    Points
    9 208
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    En fait, à ce niveau de la réflexion, la question à se poser, c'est de savoir si HFSQL CS est adapté.
    Dans la cas de sa requête, non.

    Dans le cas de requêtes "basiques", cela fonctionne très bien. Si tu veux (dois) garder hfcs, il faut contourner en utilisant des "ruses" du type de celle que j'ai exposé.

    Et je comprends que ça te fasse bondir tbc92
    Commencez toujours appuyer sur la touche F1 et puis n'hésitez à passer par un moteur de recherche...
    Le forum est fait pour répondre aux questions : pas la peine de me les envoyer par MP. Merci.

    Sur internet, tout est vrai ! Honoré de Balzac
    Make it real not fantasy... Herman Rarebell

Discussions similaires

  1. [WD19] Déploiement d'une application avec HFSQL client/serveur
    Par jjacques68 dans le forum WinDev
    Réponses: 1
    Dernier message: 03/11/2014, 08h39
  2. Installation site Joomla local sur serveur OVH avec Filezilla
    Par ExcelTD dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 31/10/2010, 19h09
  3. Conf DNS pour serveur mail avec IP dynamique ?
    Par ovh dans le forum Réseau
    Réponses: 9
    Dernier message: 14/06/2004, 22h55
  4. Serveur Linux avec clients Windows
    Par ostaquet dans le forum Installation
    Réponses: 2
    Dernier message: 01/08/2002, 15h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo