2011-03-17 7 views
2

Je travaille sur un script avec des filtres de produits. Tout fonctionne bien mais c'est trop lent. La raison en est trop de requête. Query5 sélectionne environ 200 entrys. Requête12 "recherche" dans 130.000 entrées.Script trop lent, mysql rejoindre?

Est-il possible de faire une jointure mysql ou quelque chose de plus rapide avec moins de requêtes?

<?php 
       $query5 = mysql_query("SELECT id,fabrikant,naam FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren.""); 
       while($row5 = mysql_fetch_assoc($query5)){ 

        foreach($_GET as $key=>$value){ 
          if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0"){ 

           $query12 = mysql_query("SELECT COUNT(id) as aantal FROM producten_specs WHERE name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' AND product_id='".secure_in($row5['id'])."'"); 
           $data12 = mysql_fetch_assoc($query12); 

           if($data12['aantal']){ 
            $product_present = TRUE; 
           } else { 
            $product_present = FALSE; 
            break; 
           } 

          } 
        } 
        if($product_present){ 
         echo $row5['id']."<br />"; 
         $product_present = FALSE; 
        } 
       } 
    ?> 

Merci.

EDIT: Ok, nouveau départ. J'espère que son meilleur (plus rapide) de cette façon:

 //Select products from category and brand 
     $query5 = mysql_query("SELECT id FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren.""); 
     while($row5 = mysql_fetch_assoc($query5)){ 
      $query5_ids .= $row5['id'].", "; 
     } 
     //Remove last ',' 
     $query5_ids = substr($query5_ids, 0, -2); 

     //Get all $_GET's 
     foreach($_GET as $key=>$value){ 
      if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0"){ 
       $specs_gets .= $key.",".$value.";"; 
       $count_gets++; 
       $selection .= "name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' OR "; 
      } 
     } 
     //Remove last ';' 
     $specs_gets = substr($specs_gets, 0, -1); 


     //$selection = " AND ".substr($selection, 0, -4); 
     $selection = substr($selection, 0, -4); 


     //THE query.. 
     //$query12 = mysql_query("SELECT product_id FROM producten_specs WHERE product_id IN ('".secure_in($query5_ids)."') ".$selection." ORDER BY product_id ASC"); 
     $query12 = mysql_query("SELECT product_id FROM producten_specs WHERE ".$selection." ORDER BY product_id ASC"); 
     while($row12 = mysql_fetch_assoc($query12)){ 

      if($product_hold == $row12['product_id']){ 
       $product_hold_count++; 
      } else { 
       $product_hold_count = FALSE; 
       $product_hold = $row12['product_id']; 
       $product_hold_count = 1; 
      } 

      if($product_hold_count == $count_gets){ 

       $query12_ids_ok .= $row12['product_id'].", "; 
       $count_products++; 
      } 

     } 
     //Remove last ',' 
     $query12_ids_ok = substr($query12_ids_ok, 0, -2); 

EDIT2 Lien vers le site: snip

EDIT3 Quelques informations supplémentaires:

Exemple de l'URL:

index.php 
?p=categorie 
&id=5 
&brand=Asus 
&Display_inch=0 
&Resolution=0 
&Buldin_camera=0 
&Chipset=0 
&Processor-speed=2400+MHz 
&Processorfamilie=0 
&Hard+disk-interface=0 
&Total+capacitie=500+GB 
*snip (because its very long)* 
&submit=Submit+Filter 

La base de données:

product_new (contient 3500 entrys) - Contient des informations produit générales

id, fournisseur, prix, icecat_cat, nom, etc.

1, Asus, 500, ordinateur portable, K72F

product_specs (contient 130.000 entrys) - spécifications du produit contians

id

, product_id, chat, nom, valeur

1, 1, processeur, processeur vitesse, 2400 Mhz

2, 1, Disque Dur, Total-capacitie, 500 Go

EDIT4 Je reçois de plus près, voir le code dans mon premier edit, seul le code produit IN ('".secure_in ($ query5_ids)."') doit être ajouté dans query12. Ensuite, j'obtiens les résultats que je veux et beaucoup plus vite! N'importe qui? Parce que vous êtes hollandais (vous pouvez le voir dans votre programmation), je posterai aussi ma réponse en néerlandais.

+1

200 lignes dans * producten_new * 10 variables GET = requêtes 2K!vous avez besoin de restructurer !!! – RobertPitt

+0

Index? À quelle fréquence la boucle for est-elle exécutée? –

+0

C'est un peu complexe, les perheps séparent les choses. Il ralentit parce que vous avez et foreach dans une déclaration while. Quelques lignes fonctionneront bien, mais si les données augmentent, le temps augmente également. – B4NZ41

Répondre

0

Got it !! Merci de coopérer!

//Producten selecteren uit categorie en merk 
    $query5 = mysql_query("SELECT id FROM producten_new WHERE icecat_cat='".secure_in($obj->icecat)."'".$selecteren.""); 
    while($row5 = mysql_fetch_assoc($query5)){ 
     $query5_ids .= $row5['id'].", "; 
    } 
    //Laatste , weg halen 
    $query5_ids = substr($query5_ids, 0, -2); 

    //Gets op een rijte zetten 
    foreach($_GET as $key=>$value){ 
     if($key != "p" AND $key != "id" AND $key != "merk" AND $key != "submit" AND $value != "0"){ 
      $specs_gets .= $key.",".$value.";"; 
      $aantal_gets++; 
      $uiteindelijk_selecteren .= "name='".secure_in(str_replace("_", " ", $key))."' AND value='".secure_in($value)."' OR "; 
     } 
    } 
    //Laatste ; weg halen 
    $specs_gets = substr($specs_gets, 0, -1); 


    //$uiteindelijk_selecteren = " AND ".substr($uiteindelijk_selecteren, 0, -4); 
    $uiteindelijk_selecteren = substr($uiteindelijk_selecteren, 0, -4); 


    //Overeenkomend met de get's selecteren 
    $query12 = mysql_query("SELECT product_id FROM producten_specs WHERE product_id IN (".secure_in($query5_ids).") AND ".$uiteindelijk_selecteren." ORDER BY product_id ASC"); 
    while($row12 = mysql_fetch_assoc($query12)){ 

     if($product_onthouden == $row12['product_id']){ 
      $product_onthouden_aantal++; 
     } else { 
      $product_onthouden_aantal = FALSE; 
      $product_onthouden = $row12['product_id']; 
      $product_onthouden_aantal = 1; 
     } 

     if($product_onthouden_aantal == $aantal_gets){ 

      $query12_ids_ok .= $row12['product_id'].", "; 
      $aantal_producten++; 
     } 

    } 
    //Laatste , weg halen 
    $query12_ids_ok = substr($query12_ids_ok, 0, -2); 
+0

Heureux que ça a marché! Vous devriez alors considérer «accepter» la solution qui vous a apporté le plus d'intrants. (l'utilisateur à faible acceptation a tendance à recevoir moins de réponses au fil du temps) – Rodolphe

1


Ik heb 1 puntje al als Snelheid verbetering: Omdat je $ product_niet_aanwezig op vrai zet doet hij de repos van de foreach wel sneller maar het hij doet niet te min. Je peux entendre une déclaration de rupture erin zetten. Dan "breakt" die uit de foreach boucle.


J'ai un point d'amélioration: Parce que vous définissez product_niet_aanwezig $ true, il continuera de faire le reste de la boucle foreach beaucoup plus rapide, mais il le fera encore. Vous pouvez également utiliser une instruction break pour "sortir" de la boucle foreach.

+0

J'utilise la pause maintenant, merci! Mais pas vraiment un tweak de préformance. – Roy

1
  • Vous devez d'abord vérifier les index sur toutes les clés utilisées dans les conditions 'where'. (nom, valeur, id_produit dans la table producten_specs par exemple)

  • query12 ne peut être appelée qu'une seule fois: votre boucle doit générer une grande condition, puis une seule requête est envoyée. Comme vous travaillez avec « count », vous devriez être en mesure de construire quelque chose comme

COUNT (id) DE producten_specs OÙ [la condition construite dans votre boucle] GROUP BY product_id (cela peut ne pas être totalement précis si)

  • Je ne connais pas votre db shema, mais j'essaie de créer une vue avec une requête aussi performante que possible. Une vue avec une jointure en utilisant votre clé product_id et liste uniquement les colonnes dont vous avez besoin, serait plus facile à interroger

Mes 2 cents :)

+0

J'ai modifié mon post de départ et ajouté des informations de base de données. J'espère que c'est plus clair maintenant. – Roy

+0

Je ne suis pas totalement dans votre problématique. Bien que je peux recommander de travailler avec de petites étapes: - continuer à exécuter votre query12 avec un résultat à partir des résultats de query5 - essayer d'afficher le code SQL généré, et exécuter que la requête select dans un éditeur DB (phpmyadmin, mysql workbench , etc.) Dès que vous obtenez une requête de travail, vous pouvez essayer de "mettre à niveau" la façon dont vous l'avez généré. Avec votre nouveau code, votre query5 fonctionne-t-elle? – Rodolphe

+0

Query5 fonctionne très bien. Je n'ai aucune idée de comment obtenir les résultats. Par exemple, comment sélectionner 1 et 2 (à partir de l'exemple dans start post à product_specs, voir edit3) par product_id à partir de query5 et nom et valeur à partir d'un $ _GET? – Roy

1

Votre code

je peux » Je ne vois pas ce qui ne va pas avec votre code puisque je suis italien et je ne comprends pas la vraie logique derrière ce script. Malgré cela, il me semble que vous exécutez une boucle qui exécutera des milliers de requêtes, ou une seule (à cause de la condition if), dans les deux cas, je suggérerais l'utilisation d'instructions PDO qui mettent en cache les requêtes et font ils courent plus vite la deuxième fois.

AOP Fièvre

Depuis la deuxième requête est exécutée dans une boucle, je vous suggère d'utiliser PDO qui stockera la déclaration et chaque fois que l'instruction est exécutée, il est plus rapide.

Je cite le manuel ici:

En utilisant une déclaration préparée à l'application évite de répéter l' analyser/compilation/cycle optimize. Ce signifie que la préparation des états utilisent moins de ressources et exécutent plus rapidement

Je veux vous faire remarquer que PDO empêche également de l'injection SQL:

[...] le développeur peut être sûr qu'aucune injection SQL se produira [...]

Index

Vous devez définir des index dans la base de données de sorte que l'interrogation de tables spécifiques prendra moins de temps. Fondamentalement, les index SQL sont similaires aux index de livres, ils fournissent un moyen rapide de localiser les informations.

+0

Merci pour la réponse mais je n'ai aucune expirence avec PDO. Je vais suivre quelques tutoriels à ce sujet. J'espère qu'il peut faire ce que je veux. – Roy

+0

@Roy, PDO est l'avenir. J'ai essayé MySQL, MySQL et PDO et c'est une révolution. Croyez-moi. – Shoe

+0

J'ai lu quelques tutoriels et PDO n'est pas si difficile mais avec la même requête (query12) le script reste lent ...? Le script doit changer totalement. Je n'ai aucune idée de comment ... J'ai essayé (voir edit2 dans mon post de départ). – Roy