[RESOLU] optimisation moteur de recherche

Mammouth du PHP | 790 Messages

02 déc. 2012, 00:28

Salut a tous,
voila sur un site j'ai un petit moteur de recherche:
    <?php
    //On se connecte a la base de donnee
    mysql_connect('localhost', 'root', '');
    mysql_select_db('genea_bdd');

    // si le formulaire est posté
    if (isset($_POST['q'])) {
        // je protège les caractères spéciaux
        // je renvoie une chaine en minuscules

        $q = mysql_real_escape_string(strtolower($_POST['q']));

        // je crée une variable qui contient la requete SQL 
        $sql = "SELECT id_chien, nom, status, affixe, aff_url, sex, proprietaire, livre, lof
                    FROM chien
                    WHERE
                    status = 'Valide'
                    AND
                    LOWER( nom ) LIKE  '$q%'
                    OR LOWER( mc ) LIKE  '%$q%'
                    OR LOWER( lof ) LIKE  '$q%'
                    
                    ORDER BY nom";

        // J'envoie une requete au serveur
        $req = mysql_query($sql);

        // Je trouve le nombre de lignes d'un résultat MySQL
        if (mysql_num_rows($req)) {
            // je fait une boucle qui cherche chaque enregistrement 
            while ($dnn = mysql_fetch_array($req)) {

                $Chaine = $dnn['lof'];
                $Chaine = str_replace("/", "", $Chaine);
                ?>    
                <tr>
                    <!--
                        <td height="50px">
                            <img src="photo/upload_pic/P_<?php echo $dnn['livre'] . $Chaine; ?>.jpg" />
                        </td>
                    -->
                    <td height="25px"> &nbsp;&nbsp;
                        <img src="webroot/images/<?php echo nl2br(stripslashes($dnn['sex'])); ?>.png" title="Berger belge malinois <?php echo nl2br(stripslashes($dnn['sex'])); ?>"/>
                        &nbsp;&nbsp;      
                        <a href="pedigree.php?malinois=<?php echo $dnn['id_chien']; ?>_<?php echo $dnn['nom']; ?>_<?php echo stripslashes($dnn['aff_url']); ?>">
                            <strong><?php echo nl2br(stripslashes($dnn['nom'])); ?> <?php echo nl2br(stripslashes($dnn['affixe'])); ?></strong>
                        </a> 
                        <br />
                        &nbsp;&nbsp;&nbsp; 
                        Berger Belge Malinois | <?php echo nl2br(stripslashes($dnn['proprietaire'])); ?> 

                    </td>

                    <td>
                <center>
                    <?php echo $dnn['livre']; ?> <?php echo $dnn['lof']; ?>
                </center>
            </td>
            </tr>    
            <tr>
                <td colspan="3">
                    <div class="content_box_2"></div>
                </td>
            </tr>

            <?php
        }
    } else {
        echo '</table><br /><center><strong><font color="red">Aucun r&eacute;sultat</font></strong></center><br /><br />';
    }
} else {
    header('location: 404.php');
}
?>
la en comptant comme ça, les résultats sorte au bout de 14 secondes (en ligne), je cherche donc des solutions pour descendre ce temps.
avez vous des idées ?
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Mammouth du PHP | 790 Messages

02 déc. 2012, 00:32

Au fait, c'est une requete ajax, le moteur fonctionne façon google, normalement au fur et a mesure qu'on entre la recherche, les résultats changent juste en dessous...
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Eléphanteau du PHP | 10 Messages

02 déc. 2012, 00:41

tu peux peut-être rajouter des
echo time()
à différents endroits de ton code pour identifier la partie qui prend tant de temps

Mammouth du PHP | 790 Messages

02 déc. 2012, 00:55

ah, je vais chercher car je ne connais pas, merci...
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Mammouth du PHP | 790 Messages

02 déc. 2012, 01:57

Bien, je ne vois pas ce que tu veux dire avec time()
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Eléphant du PHP | 229 Messages

02 déc. 2012, 08:38

Bonjour,

Aucune idée mais lol :
"Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part."
La requête hors php est aussi longue dans ton sgbd ?

Bon codage.

Mammouth du PHP | 2278 Messages

02 déc. 2012, 10:12

Je ne sais pas si ça gagnerait grand chose, mais on doit pouvoir enlever lower() car dixit la doc confirmant mes tests:
"Les deux exemples suivants illustrent le fait que les comparaisons de chaînes de caractères ne sont pas sensibles à la casse à moins qu'une des opérandes soit une chaîne binaire(??? j'ai une vague idée du sens de ce gala de matelas). "
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Avatar du membre
Mammouth du PHP | 1609 Messages

02 déc. 2012, 13:21

Salut Steeve, y a beaucoup de lignes dans la table ?
A priori, ce qui pompe du temps, je pense aussi que c'est la requête. Tu pourrais transformer les colonnes du where en index, ça devrait faire gagner du temps si c'est pas fait.
Pareil, comme dit sirakawa, le lower n'est pas forcément indispensable dépendamment du type de la colonne. Sans certitude je crois que les varchar sont insensibles à la casse lors d'une comparaison contrairement au text (à moins que ce soit l'inverse, je ne sais plus) tu peux surement trouver l'info dans la doc MySQL.
Après sauf à faire un système de cache des résultats je vois pas trop comment tu pourrais réduire le temps de traitement. Mais un système de cache avec un champ de recherche libre à la saisi, ça peux vite devenir lourd en terme de stockage.

EDIT je pense bien à une autre méthode pour faire cette autocompletion. S'il n'y a pas des milliers de lignes dans la table, tu pourrais générer un tableau, avec par exemple en index l'id de la ligne et en valeur le nom du toutou, que tu pourrais stocker dans une variable javascript à l'aide de json_encode et la complétion irait chercher dans ce tableau au lieu de faire une requête. Le traitement se passerai en javascript par comparaison de chaîne en bouclant sur le tableau. Peut être que cela pourrait être plus rapide.
Modifié en dernier par Saian le 02 déc. 2012, 13:28, modifié 2 fois.
Développeur web depuis + de 20 ans

Mammouth du PHP | 790 Messages

02 déc. 2012, 13:23

je viens de faire 2 ou 3 tests et avec la requete comme ça
$sql = "SELECT id_chien, nom, status, affixe, aff_url, sex, proprietaire, livre, lof
                    FROM chien
                    WHERE
                    status = 'Valide'
                    AND
                     nom  LIKE  '$q%'
                    
                    ORDER BY nom";
le resultat est presque identique...
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Avatar du membre
Mammouth du PHP | 1609 Messages

02 déc. 2012, 13:29

La colonne nom est bien indexée dans la base de données ? et tu as combien de lignes (beaucoup j'imagine pour que le traitement soit aussi long) ?
Développeur web depuis + de 20 ans

Mammouth du PHP | 790 Messages

02 déc. 2012, 13:32

ARF, super désolé j'ai plusieurs moteurs sur cette page et le moteur dont je parle est celui ci...
<?php
session_start();
include '../../includes/classes/connexion/Mysql.class.php';
include '../../includes/config.php';
include '../../includes/template/javascript.php';
?>
<table class="table well table-hover"> 
    <?php
    // si le formulaire est posté
    if (isset($_POST['moteur'])) {

        $q = strtolower(addslashes($_POST['moteur']));

        $bdd = new MySqlClass();
        $bdd->MysqlOpen($SqlHost, $SqlUser, $SqlPass, $SqlBdd);
        $req = $bdd->MysqlSelectPerso("SELECT 
                                        ce.id_chien       AS   id_chien,
                                        ce.nom            AS   nom,
                                        ce.id_affixe      AS   id_affixe_ce,
                                        ce.proprietaire   AS   proprietaire,
                                        ce.sex            AS   sex,
                                        ce.livre          AS   livre,
                                        ce.lof            AS   lof,
                                        ce.video          AS   video,
                                        ce.photo          AS   photo,

                                        af.id_affixe      AS   id_affixe,
                                        af.affixe         AS   affixe,
                                        af.prefixe        AS   prefixe,
                                        af.affixe_url     AS   aff_url

                                    FROM chien ce

                                    INNER JOIN affixe af  ON  ce.id_affixe = af.id_affixe

                                    WHERE LOWER( nom ) LIKE  '$q%' OR LOWER( lof ) LIKE  '$q%'");
        if ($req) {

            // Affichage
            for ($i = 0; $i < count($req); $i++) {
                $ligne = $req[$i];

                // suppression des ' du nom pour l'url
                $nom_url = $ligne['nom'];
                $Chaine = $nom_url;
                $Chaine = str_replace("'", "-", $Chaine);

                if (!empty($ligne['video'])) {
                    $vi = '<a href="#" rel="tooltip" data-placement="right" title="Ce pedigree contient une vidéo"><i class="icon-facetime-video"></i></a>';
                } elseif (!empty($ligne['photo'])) {
                    $vi = '<a href="#" rel="tooltip" data-placement="right" title="Ce pedigree contient une photo"><i class="icon-camera"></i></a>';
                } else {
                    $vi = '';
                }

                echo '
                      <tr>
                      <td width="50%">
                      <div class="tooltip-demo">
                          </i> <img src="assets/img/' . nl2br(stripslashes($ligne['sex'])) . '.png" title="Berger belge malinois' . nl2br(stripslashes($ligne['sex'])) . '"/>
                          <a href="' . $ligne['id_chien'] . '-pedigree-malinois-' . stripcslashes(strtolower($Chaine)) . '-' . $ligne['aff_url'] . '.html">    
                          <strong>' . stripcslashes($ligne['nom']) . '&nbsp;' . stripcslashes($ligne['prefixe']) . '&nbsp;' . stripcslashes($ligne['affixe']) . '</strong>
                          </a>
                          ' . $vi . '
                          <br />
                          ' . $ligne['proprietaire'] . ' 
                      </div>
                      </td>
                      ';

                if (isset($_SESSION['SESS_MEMBER_ID'])) {
                    if (isset($_SESSION['SESS_GROUPE']) and $_SESSION['SESS_GROUPE'] == 'Admin' or $_SESSION['SESS_GROUPE'] == 'Redacteur') {
                        echo'<td width="50%" class="hidden-phone">
                  <br /><p class="pull-right">Malinois ' . $ligne['livre'] . '&nbsp;' . $ligne['lof'] . '&nbsp;&nbsp;&nbsp;[<a href="#">Modifier</a>] | [<a href="#">Supprimer</a>]</p>
                  </td>
                  </tr>';
                    } elseif ($_SESSION['SESS_GROUPE'] == 'Membre') {
                        echo'<td width="50%" class="hidden-phone">
                  <br /><p class="pull-right">Malinois ' . $ligne['livre'] . '&nbsp;' . $ligne['lof'] . '</p>
                  </td>
                  </tr>';
                    }
                } else {
                    echo'<td width="50%" class="hidden-phone">
                  <br /><p class="pull-right">Malinois ' . $ligne['livre'] . '&nbsp;' . $ligne['lof'] . '</p>
                  </td>
                  </tr>';
                }
            }
        } else {
            echo '</table><p class="center"><strong><font color="red">Aucun r&eacute;sultat</font></strong></><br /><br />';
        }
    } else {
        header('location: 404.php');
        // var_dump($_GET['malinois']);
    }
    ?>
</table>
et ce n'est plus du tout le même, ce sont vos test qui m'on montrer que je me trompais de moteur....
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Mammouth du PHP | 790 Messages

02 déc. 2012, 13:34

Saian, ya pas des milliers de ligne mais ça viendras...
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.

Eléphanteau du PHP | 10 Messages

02 déc. 2012, 13:39

la fonction time() te donne le timestamp au moment du moment exact où tu appelle la fonction,
si tu met un echo time(); au début de ton script, puis un autres après avoir exécuté ta requête, puis un autre dans ta boucle, et un dernier à la fin de ton script ça te donnera les heures exactes à chaque étape du script et comme ça, en faisant la différence entres les timestamp tu sauras combien de temps a pris chaque étape, ce qui te permet ensuite de savoir quelle est la partie de ton script qui prend tant de temps.

en version améliorée tu peux aussi utiliser la fonction microtime() qui est plus précise.
// au début de ton scrip tu mets :
$t_initial = microtime();

// ...

// après ta requette tu mets
echo "le script tourne depuis ". ($microtime() - $t_initial) . "<br />" ;

// ...
// à l'intérieur de ta boucle idem
echo "le script tourne depuis ". ($microtime() - $t_initial) . "<br />" ;

// et à la fin de ton script idem
echo "le script tourne depuis ". ($microtime() - $t_initial) . "<br />" ;
à mon avis il est probable que tes 14 secondes d'exécution soient en fait dans la partie javascript de ton code et pas forcément dans la partie php

Avatar du membre
Mammouth du PHP | 1609 Messages

02 déc. 2012, 13:41

Je me disais la même chose que audaxman (le javascript). ;)

EDIT pour en dessous : c'est pour ça que l'idée du js qui rame parait cohérent, le problème semblant venir du côté client.
Modifié en dernier par Saian le 02 déc. 2012, 13:46, modifié 1 fois.
Développeur web depuis + de 20 ans

Mammouth du PHP | 790 Messages

02 déc. 2012, 13:43

Attendez, je viens de faire faire un test a Saian et chez lui le résultat sort en 1 seconde
a savoir, je suis en bout de ligne et a priori, j'ai 1 mega 8 d’après france teleccom
Les fautes de grammaire et d'orthographe contenu dans mes postes sont sous copyright, vous pouvez les utiliser pour un usage personnelle mais vous ne devrez en aucun cas les utiliser a des fins commercial sans une autorisation écrite de ma part.