php - MySQL Performance - How to accelerate query for Build-Up / Burn-Down Chart? -


i working on application generate buildup , burndown chart in mysql/php use generate using nvd3.js

my code below loops every day min max date of dataset can filtered.

so far, run query 1 time every day, realize can add tremendous amount of delay, 10 seconds wait load.

how can generate data more quickly?

invoking code

public function burnupaction()     {         $actionitemtable = $this->getactionitemtable();         $burnup =  array('totalactionitems' => $actionitemtable->getburnup('assigneddate'),                          'ecditems' => $actionitemtable->getburnup('ecd'),                          'originaldueitems' => $actionitemtable->getburnup('duedate'),                          'actualopenitems' => $actionitemtable->getburnup('closeddate'));         $this->response->setcontent(json_encode($burnup));         return $this->response;     } 

build chart code

for ($y = $minyear; $y <= $maxyear; $y++) {         if ($y == $minyear)             $startmonth = $minmonth;         else             $startmonth = 1;          if ($y == $maxyear)             $finishmonth = $maxmonth;         else             $finishmonth = 12;           ($m = $startmonth; $m <= $finishmonth; $m++)         {                                    if ($m < 10)             {                 $month = "0$m";             }             else              {                 $month = "$m";             }             $monthstr = $this->getmonth($m);               ($d = 1; $d <= 31; $d++)             {                     if ($d< 10)                     {                         $day = "0$d";                     }                     else                      {                         $day = "$d";                     }                      $dt = "$monthstr $day $y";                     $start = "$y-$month-$day";                     $end = "$y-$month-$day";                      $where = $this->filterstring();                     $filtered = "select * actionitems " . $where;                      if ($field == 'assigneddate')                     {                         array_push($subsel, "(select '$dt' assigneddate, sum(case when assigneddate between '$start' , '$end' 1 else 0 end) 'numactionitems' ($filtered) s)");                     }                     if ($field == 'ecd')                     {                         array_push($subsel, "(select '$dt' ecd, sum(case when ecd between '$start' , '$end' 1 else 0 end) 'numactionitems' ($filtered) s)");                     }                     if ($field == 'duedate')                     {                         array_push($subsel, "(select '$dt' duedate, sum(case when duedate between '$start' , '$end' 1 else 0 end) 'numactionitems' ($filtered) s)");                     }                     if ($field == 'closeddate')                     {                         array_push($subsel, "(select '$dt' closeddate, sum(case when closeddate between '$start' , '$end' 1 else 0 end) 'numactionitems'  ($filtered) s)");                     }             }         }     }      if (count($subsel) == 0)         return array();       $sub = join(" union ", $subsel);      if ($field == 'assigneddate')     {         $sql = "select assigneddate, (@csum:= @csum + numactionitems) totalactionitems ($sub) t";     }     if ($field == 'ecd')     {         $sql = "select ecd, numactionitems ecditems, (@csum:= @csum + numactionitems) totalactionitems ($sub) t";     }     if ($field == 'duedate')     {         $sql = "select duedate, numactionitems originaldueitems, (@csum:= @csum + numactionitems) totalactionitems ($sub) t";     }     if ($field == 'closeddate')     {         $sql = "select closeddate, numactionitems acutalcloseditems, (@csum:= @csum + numactionitems) totalactionitems ($sub) t";     } 

generated carts (buildup on top / burndown on bottom)

buildup/burdown charts

the main part of query this:

select 'mar 01 2015' assigneddate,             sum(case                   when assigneddate between '2015-03-01' , '2015-03-01'                 1                   else 0                 end)      'numactionitems'        (select *                actionitems) s; 

this query has 1 drawback: per date table actionitems scanned.

to improve query can written as:

select 'mar 01 2015' assigneddate,             count(*) 'numactionitems'      actionitems      assigneddate between '2015-03-01' , '2015-03-01'; 

this still not pretty, next step required: alternative dates be:

select assigneddate,             count(*) 'numactionitems'      actionitems      assigneddate between '2015-03-01' , '2015-03-30'      group assigndate; 

this give 'numactionitems' per date.

adding @csum outer query:

select assigneddate,    ( @csum := @csum + numactionitems ) totalactionitems  (    select assigneddate,             count(*) 'numactionitems'      actionitems      assigneddate between '2015-03-01' , '2015-03-30'      group assigndate) 

should give same result.

also add index:

create index idx_ai_nn_1 on actionitems(assigneddate); 

this index work if date range scanning table << smaller number of rows selecting.


Comments