2011-11-11 3 views
2

Il s'agit d'une question d'efficacité/meilleure pratique. Espérant recevoir un feed-back sur la performance. Tout conseil est grandement appréciée.Efficacité de l'appel de la base de données Codeigniter

Voici donc un petit historique de ce que j'ai configuré. J'utilise codeigniter, l'installation de base est assez similaire à toutes les autres relations de produit. Les tableaux de base sont: Marques, produits, catégories. En plus de ces tableaux, il y a un besoin de feuilles d'installation, de matériel de marketing et de couleurs.

J'ai créé des tables de relations: Brands_Products Products_Colors Products_Images Products_Sheets

J'ai aussi une table Categories_Relationships qui contient toutes les relations avec les catégories. Les feuilles d'installation, etc. peuvent avoir leurs propres catégories, mais je ne voulais pas définir une table de relations de catégories différente pour chaque type car je ne pensais pas que ce serait très extensible.

Sur la face avant, je trier par marques et catégories.

Je pense que cela couvre l'arrière-plan maintenant à la partie d'efficacité. Je suppose que ma question concerne principalement la météo, il serait préférable d'utiliser des jointures ou de faire des appels séparés pour renvoyer des pièces individuelles de chaque article (couleurs, images, etc.)

Ce que j'ai codé actuellement, c'est de travailler, et de bien trier Je pense que je peux améliorer la performance, car cela prend du temps pour retourner la requête. En ce moment, il revient environ 45 articles. Voici ma première fonction, elle saisit tous les produits et ses infos.

Il fonctionne en sélectionnant d'abord tous les produits et en joignant l'information de sa marque. Ensuite, en boucle à travers le résultat, j'ai mis en place les informations de base, mais pour les catégories images et installations, j'utilise des fonctions qui renvoie chacun des éléments respectés.

public function all() 
    { 
     $q = $this->db 
        ->select('*') 
        ->from('Products') 
        ->join('Brands_Products', 'Brands_Products.product_id = Products.id') 
        ->join('Brands', 'Brands.id = Brands_Products.brand_id') 
        ->get(); 

     foreach($q->result() as $row) 
     { 
      // Set Regular Data 
      $data['Id'] = $row->product_id; 
      $data['Name'] = $row->product_name; 
      $data['Description'] = $row->description; 
      $data['Brand'] = $row->brand_name; 
      $data['Category'] = $this->categories($row->product_id); 
      $data['Product_Images'] = $this->product_images($row->product_id); 
      $data['Product_Installs'] = $this->product_installs($row->product_id); 
      $data['Slug'] = $row->slug; 


      // Set new item in return object with created data 
      $r[] = (object)$data; 
     } 


     return $r; 
    } 

Voici un exemple de l'une des fonctions utilisées pour obtenir les pièces individuelles.

private function product_installs($id) 
    { 
     // Select Install Images 
     $install_images = $this->db 
        ->select('*') 
        ->where('product_id', $id) 
        ->from('Products_Installs') 
        ->join('Files', 'Files.id = Products_Installs.file_id') 
        ->get(); 

     // Add categories to category object 
     foreach($install_images->result() as $pImage) 
     { 
      $data[] = array(
         'id' => $pImage->file_id, 
         'src' => $pImage->src, 
         'title' => $pImage->title, 
         'alt' => $pImage->alt 
         ); 
     } 

     // Make sure data exists 
     if(!isset($data)) 
     { 
      $data = array(); 
     } 

     return $data; 
    } 

Encore une fois, je suis vraiment à la recherche de conseils sur ce qui est le plus efficace et le meilleur moyen de le faire. J'apprécie vraiment tout conseil, ou information.

Répondre

0

Je pense que votre approche est correcte. Il n'y a que quelques options: 1) chargez d'abord votre liste de produits, puis bouclez et chargez les données requises pour chaque ligne de produit. 2) créez d'abord une grosse jointure sur toutes les tables, puis faites une boucle sur un produit cartésien (peut-être massif). La seconde pourrait devenir plutôt laide à analyser. Par exemple, si vous avez le produit A et le produit B, le produit A a installé 1, installé 2, installé 3 et le produit B a installé 1 et installé 2, lorsque le résultat est Produit A Installation 1 Produit A Installer 2 produit A Installation 3 produit B Installer 1 produit B Installez 2

maintenant, ajoutez vos images et les catégories à la jointure et il pourrait devenir énorme.

Je ne suis pas sûr de la taille de vos tables, mais le retour de 45 lignes ne devrait pas être long. La chose évidente à assurer (et vous l'avez probablement déjà fait) est que product_id est indexé dans toutes les tables ainsi que dans vos tables brands_products et autres. Sinon, vous effectuerez une analyse de table.

La question suivante est de savoir comment afficher vos données à l'écran.Donc, vous obtenez tous les produits. Avez-vous besoin de charger des catégories, des images, des installations lorsque vous obtenez une liste de produits? Si vous affichez simplement des produits à l'écran, vous pouvez attendre de charger ces données jusqu'à ce que l'utilisateur sélectionne un produit qu'il consulte.

Sur une note de côté, une raison quelconque vous convertissez votre tableau pour objet

$r[] = (object)$data; 

En outre, dans la deuxième fonction, vous pouvez simplement ajouter

$data = array(); 

avant la foreach, au lieu de

// Make sure data exists 
if(!isset($data)) 
{ 
    $data = array(); 
} 
+0

Je suppose que vous avez raison, j'appelle toutes les données quand ce n'est pas nécessaire, je ne sais pas pourquoi cela m'a échappé. J'ai utilisé mon approche actuelle pour éviter exactement ce que vous avez décrit ci-dessus, mais je n'étais pas sûr si je causais une grande différence de performance en faisant cela. Je le convertis en objet afin que je puisse utiliser la syntaxe -> pour tout. au lieu de -> parfois et array ['key'] d'autres fois. merci pour le conseil, je vous remercie de prendre le temps. – jchamb

+0

de rien. Quelques autres améliorations que vous pourriez vouloir considérer: $ q-> result() dans votre première fonction renvoie déjà un tableau d'objets. Vous convertissez chacun en tableau et ensuite en objet. 1) Si vous insistez sur le changement des noms de colonnes de la base de données à ce que php voit, d'accord. (signifiant id vs product_id, nom vs product_name). Sinon retrun $ q-> result() et vous avez terminé. 2) sauter la création de tableau et aller directement à l'objet. $ data = new stdClass(); $ data-> id = $ row-> product_id, etc –

+0

Merci, je vais changer cela au lieu de convertir d'avant en arrière. La raison pour laquelle je change certains noms, c'est que quelqu'un d'autre s'occupe de l'interface, voulait que ce soit aussi facile que possible pour eux de comprendre. – jchamb

0

Vous pouvez essayer ceci:

  1. Recherche tous les produits
  2. Obtenir tous les ID de produit de l'étape 1
  3. Interrogation toutes les images d'installation qui a un ID de produit de l'étape 2, triées par produit ID
  4. Itérer à travers les produits à partir de l'étape 1 et ajoutez les résultats à l'étape 3

Cela vous amène de 46 requêtes (pour 45 produits) à 2 requêtes, sans jointures supplémentaires.

Vous pouvez également utiliser les codes Query Caching de CodeIgniter pour améliorer encore les performances, si cela vaut la peine d'écrire le code pour réinitialiser le cache lorsque les données sont mises à jour.

Faire plus de travail en PHP est généralement mieux que faire le travail en MySQL en termes d'évolutivité. Vous pouvez facilement modifier PHP avec des équilibreurs de charge et des serveurs Web. La mise à l'échelle de MySQL n'est pas aussi facile en raison des problèmes de simultanéité.

+0

Je prévois d'intégrer de la mise en cache, je n'y suis pas encore arrivé, je voulais toujours m'assurer que je n'étais pas complètement efficace dans la façon dont j'appelais à la base de données plusieurs fois. Merci pour le feed back, je vais jouer avec certains et voir ce que je peux trouver. – jchamb

+0

L'inefficacité est que la façon dont vous l'avez mis en place ne s'échelonne pas. Vous avez toujours n + 1 requêtes pour n produits, vs 2 requêtes pour n produits. Même sans mise en cache, la méthode de requête 2 est meilleure. – minboost

Questions connexes