2012-03-30 12 views
0

Wir haben eine hauseigene PHP-Webanwendung, die ein Finanzanalyse-Tool für unsere Benutzer ist. Wir verarbeiten die Finanzinformationen der Kunden, um ihre Fähigkeit zu analysieren, einen Kredit zurückzuzahlen.Der beste Weg, um mehrere Abfragen in einer Klasse zu behandeln?

Wir haben eine Klasse gebaut, die Funktionen hat, um viele Zahlen und Verhältnisse zu generieren. Wir verwenden diese, um Summen, Verhältnisse usw. auf den verschiedenen Seiten der Anwendung anzuzeigen. Wir haben viele Funktionen, die Summen und viele Funktionen generieren, die die Summen aus Funktionen verwenden, um neue Summen und Verhältnisse zu generieren. Hier ein Beispiel:

//Coverage Ratio 
public function CoverageRatio($hma) { 
    return div_check(($this->NetFarmIncome($hma) + $this->NetNonFarmIncome($hma) - $this->FamilyLivingExpenses() - $this->IncomeTaxes()), ($this->InterestPortionTermDebt($hma) + $this->PrincipalPortionTermDebt($hma))); 
} 

//Operating Expense Ratio 
public function OperatingExpenseRatio($hma) { 
    return div_check($this->FarmOperatingExpenses($hma), $this->GrossFarmIncome($hma)); 
} 

//Net Nonfarm Income 
public function NetNonfarmIncome($hma = null) { 
    $result = $this->db->query("SELECT ah.id, COALESCE(v1.h1, 0) - COALESCE(v2.h2, 0) AS h, COALESCE(v1.p1, 0) - COALESCE(v2.p2, 0) AS p, COALESCE(v1.a1, 0) - COALESCE(v2.a2, 0) AS a FROM analysis_history ah LEFT JOIN (SELECT analysis_id, ... GROUP BY analysis_id) AS v2 ON v2.analysis_id = ah.id WHERE ah.id = $this->analysisid"); 
    $row = $result->fetch_assoc(); 
    return $row['a']; 
} 

//Net Business Income 
public function NetBusinessIncome($hma = null) { 
    $result = $this->db->query("SELECT ah.id, COALESCE(v1.h1, 0) - COALESCE(v2.h2, 0) AS h, COALESCE(v1.p1, 0) - COALESCE(v2.p2, 0) AS p, COALESCE(v1.a1, 0) - COALESCE(v2.a2, 0) AS a FROM analysis_history ah LEFT JOIN (SELECT analysis_id, ... GROUP BY analysis_id) AS v2 ON v2.analysis_id = ah.id WHERE ah.id = $this->analysisid"); 
    $row = $result->fetch_assoc(); 
    return $row['a']; 
} 

Im letzten Jahr, viele Änderungen vorgenommen wurden und wir hatten viele neue Summen und Verhältnisse hinzuzufügen. Nachdem wir unsere Anwendung geändert haben, um die Seitenladezeit zu generieren und die Anzahl der ausgeführten Abfragen zu zählen, waren wir schockiert. Unsere größte Seite dauert 0,8 Sekunden und hat 122 Abfragen.

Wir haben einige Anpassungen vorgenommen, um die Anzahl der Abfragen zu verringern, aber wir konnten nur ungefähr 10 Abfragen abschneiden. Unsere durchschnittliche Seite hat ungefähr 35 Anfragen, von denen wir denken, dass sie einfach zu viel sind.

In unserer Klasse, die die Analyselogik enthält, sollten wir die Funktionen ändern, die Daten aus mehreren Funktionen ziehen (und mehrere Aufrufe an die Datenbank machen) und sie nur die einzelne Abfrage ausführen lassen? In meinem CoverageRatio-Beispiel über fragt jede Funktion in ihr tatsächlich die Datenbank ab - 6 separate Abfragen.

Welches ist der beste Weg, unseren Code besser zu optimieren? Ist es in Ordnung, wie es ist - wir mögen es so, nur für den Fall, dass wir eine Veränderung vornehmen müssen - wir ändern nur die Funktion, die diese bestimmte Summe erzeugt. Es wäre ein Albtraum, über 14 Funktionen verwalten zu müssen, die alle eine Nettoeinkommensberechnung verwenden. Wenn wir jemals ändern müssten, wie das Nettoeinkommen berechnet wird, müssten wir jede Abfrage in jeder Funktion ändern, die auf diesem Wert beruht. Danke für Ihre Hilfe!

+2

Haben Sie sich auch die Datenbank optimiert? Sicherzustellen, dass Sie eine gute Zwischenspeicherung und Indizierung (zusätzlich zu einer guten Tabellenstruktur) haben, kann eine ganze Welt von Unterschieden machen. – BenOfTheNorth

Antwort

3

Wenn Sie mehrere Dinge aus dem gleichen Satz von Tabellen berechnen, wäre es effizienter, dies mit einer einzelnen SELECT-Anweisung zu tun, die alle Berechnungen in separaten Spalten statt einer separaten SELECT-Anweisung für jede Berechnung ausführt . Sie können die Leistung möglicherweise auch verbessern, indem Sie temporäre Tabellen verwenden, um Zwischenergebnisse zu speichern, die von mehreren anderen Abfragen benötigt werden, um eine Neuberechnung dieser Werte in jeder Abfrage, die diese verwendet, zu vermeiden.

Wenn Ihre Abfragen viele Joins enthalten, verwenden Sie EXPLAIN, um zu untersuchen, wie die Datenbank diese Joins durchführt, und um festzustellen, ob Indizes hinzugefügt werden können, um die Joins effizienter zu machen. Einige gut ausgewählte Indizes können einen großen Unterschied machen.

+0

Nun - ich hatte darüber nachgedacht. Es gibt mehrere Summenberechnungen (wie Gesamtvermögen, Verbindlichkeiten usw.), die in verschiedenen Funktionen verwendet werden. Ich hatte überlegt, diese bei jeder Seitenladung zu berechnen, damit andere Funktionen sie verwenden können. Wäre das effizienter? Und ja, mehrere Berechnungen stammen aus dem gleichen Satz von etwa 10 Tabellen. Wir verwenden einen Abfrageanalysator, um sicherzustellen, dass unsere Abfragen optimiert sind. Vielleicht können wir einige der größeren Abfragen erneut aufrufen. – Jeff

+0

Alles, was Sie nur ein paar Mal tun können, ist immer effizienter, auch wenn nur ein Teil von einigen Abfragen aus dem Prozess gespeichert wird. – BenOfTheNorth

Verwandte Themen