Jeff
Jeff

Reputation: 1162

Best way to handle multiple queries in a class?

We have an in-house PHP web application that is a financial analysis tool for our users. We process customers' financial information to analyze their ability to pay back a loan.

We have built a class that has functions to generate lots of numbers and ratios. We use these to display totals, ratios, etc. throughout the different pages in the application. We have lots of functions that generate totals and lots of functions that use the totals from functions to generate new totals and ratios. Here's an example:

//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'];
}

Over the last year, lots of changes have been made and we've had to add lots of new totals and ratios. After modifying our application to generate the page load time and count the number of queries that are executed, we were shocked. Our largest page takes .8 seconds to generate and has 122 queries.

We've made some adjustments to decrease the number of queries, but we were only able to shave off about 10 queries total. Our average page has about 35 queries which we feel is just too much.

In our class which holds the analysis logic, should we change the functions that pull data from multiple functions (and make several calls to the database) and just have them perform the single query? In my CoverageRatio example about, every function in it actually queries the database--6 separate queries.

Which is the best way to better optimize our code? Is it fine the way it is--we like it this way just in case we need to make a change--we only change the function that generates that particular total. It would become a nightmare to have to manage 14+ functions that all use a net income calculation--if we ever had to modify how net income is calculated, we would have to change every query in every function that relies on that value. Thanks for your help!

Upvotes: 0

Views: 595

Answers (1)

Wyzard
Wyzard

Reputation: 34573

If you're computing multiple things from the same set of tables, it'd be more efficient to do it with a single SELECT statement that does all the computations in separate columns, rather than a separate SELECT statement for each computation.

You might also be able to improve performance by using temporary tables to hold intermediate results that are needed by multiple other queries, to avoid recomputing those values in each query that uses them.

If your queries involve a lot of joins, use EXPLAIN to study how the database is performing those joins, and see if there are any indexes you could add to make the joins more efficient. A few well-chosen indexes may make a big difference.

Upvotes: 3

Related Questions