2 Stimmen

Codeigniter Datenbankaufruf Effizienz

Dies ist eine Frage der Effizienz/Best Practice. Ich hoffe, dass ich einige Rückmeldungen zur Leistung erhalte. Jeder Rat ist sehr willkommen.

Also hier ist ein wenig Hintergrund in dem, was ich eingerichtet habe. Ich benutze Codeigniter, die grundlegende Einrichtung ist ziemlich ähnlich zu jedem anderen Produkt Beziehungen. Grundlegende Tabellen sind: Marken, Produkte, Kategorien. Oben auf diese Tabellen gibt es eine Notwendigkeit für installieren Blätter, Marketing-Materialien, und Farben.

Ich habe einige Beziehungstabellen erstellt: Marken_Produkte Produkte_Farben Produkte_Bilder Produkte_Blätter

Ich habe auch eine Tabelle Categories_Relationships, die alle Beziehungen zu Kategorien enthält. Installationsblätter usw. können ihre eigenen Kategorien haben, aber ich wollte nicht für jeden Typ eine andere Kategorie-Beziehungstabelle definieren, weil ich nicht dachte, dass das sehr ausbaufähig sein würde.

Am vorderen Ende sortiere ich nach Marken und Kategorien.

Ich denke, damit ist der Hintergrund für den Teil über die Effizienz abgedeckt. Ich schätze, meine Frage bezieht sich hauptsächlich auf das Wetter, das es besser wäre, Joins zu verwenden oder separate Aufrufe zu machen, um einzelne Teile jedes Elements zurückzugeben (Farben, Bilder, etc.)

Was ich derzeit codiert haben funktioniert, und Sortierung gut, aber ich denke, ich kann die Leistung zu verbessern, wie es einige Zeit dauern, um die Abfrage zurück. Gerade jetzt seine Rückkehr etwa 45 Elemente. Hier ist meine erste Funktion es greift alle Produkte und seine Informationen.

Es funktioniert, indem Sie zunächst alle Produkte auswählen und verbinden es Marke Informationen. dann Schleife durch das Ergebnis, das ich die grundlegenden Informationen, aber für die Kategorien Bilder und Installationen ich bin mit Funktionen, die jedes der respektierten Elemente zurückgibt.

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;
    }

Hier ist ein Beispiel für eine der Funktionen, mit denen die einzelnen Teile ermittelt werden.

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;
    } 

Ich bin also wieder auf der Suche nach Ratschlägen, wie man dies am effizientesten und am besten bewerkstelligen kann. Ich schätze wirklich jeden Rat oder jede Information.

0voto

Alexey Gerasimov Punkte 2071

Ich denke, Ihr Ansatz ist richtig. Es gibt nur ein paar Möglichkeiten: 1) Laden Sie zuerst Ihre Produktliste, dann eine Schleife, und laden Sie die erforderlichen Daten für jede Produktzeile. 2) Erstellen Sie zunächst eine große Verknüpfung über alle Tabellen, und führen Sie dann eine Schleife durch das (möglicherweise umfangreiche) kartesische Produkt. Die zweite Option könnte beim Parsen ziemlich hässlich werden. Wenn Sie zum Beispiel Produkt A und Produkt B haben, und Produkt A hat Install 1, Install 2, Install 3, und Produkt B hat Install 1 und Install 2, dann ist Ihr Ergebnis Produkt A Installation 1 Produkt A Installation 2 Produkt A Installation 3 Produkt B Installation 1 Produkt B Installation 2

Fügen Sie nun Ihre Bilder und Kategorien hinzu, und es könnte riesig werden.

Ich bin mir nicht sicher, wie groß Ihre Tabellen sind, aber die Rückgabe von 45 Zeilen sollte nicht lange dauern. Das Offensichtliche, das Sie sicherstellen müssen (und das haben Sie wahrscheinlich schon getan), ist, dass product_id in allen Tabellen sowie in den Tabellen brands_products und anderen indiziert ist. Andernfalls führen Sie einen Tabellenscan durch.

Die nächste Frage ist, wie Sie Ihre Daten auf dem Bildschirm darstellen. Sie erhalten also alle Produkte. Müssen Sie Kategorien, Bilder, Installationen laden, wenn Sie eine Liste von Produkten erhalten? Wenn Sie einfach nur Produkte auf dem Bildschirm auflisten, sollten Sie mit dem Laden dieser Daten warten, bis der Benutzer ein Produkt auswählt, das er sich ansieht.

Nebenbei bemerkt, aus welchem Grund konvertieren Sie Ihr Array in ein Objekt?

$r[] = (object)$data;

Außerdem können Sie in der zweiten Funktion einfach Folgendes hinzufügen

$data = array();

vor der foreach-Anweisung, anstelle von

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

0voto

minboost Punkte 2545

Sie können dies versuchen:

  1. Abfrage aller Produkte
  2. Alle Produkt-IDs aus Schritt 1 abrufen
  3. Abfrage aller Installationsbilder, die eine Produkt-ID aus Schritt 2 haben, sortiert nach Produkt-ID
  4. Iterieren Sie durch die Produkte aus Schritt 1 und fügen Sie die Ergebnisse aus Schritt 3 hinzu

Das bedeutet, dass Sie von 46 Abfragen (für 45 Produkte) auf 2 Abfragen kommen, ohne zusätzliche Verknüpfungen.

Sie können auch CodeIgniter's Abfrage-Caching um die Leistung noch weiter zu steigern, wenn es die Zeit wert ist, den Code zum Zurücksetzen des Cache zu schreiben, wenn Daten aktualisiert werden.

Mehr Arbeit in PHP ist im Allgemeinen besser als die Arbeit in MySQL, was die Skalierbarkeit betrifft. Sie können PHP problemlos mit Lastverteilern und Webservern skalieren. Die Skalierung von MySQL ist aufgrund von Gleichzeitigkeitsproblemen nicht so einfach.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X