Php MySQL性能-如何加速构建/烧毁图表的查询?
我正在用MySQL/PHP编写一个应用程序生成构建图和一个燃尽图,我使用NVD3.js生成它 我下面的代码每天循环使用我的数据集的从最小到最大的日期,可以对其进行筛选 到目前为止,我每天运行查询1次,我意识到这会增加巨大的延迟,大约10秒等待加载 如何更快地生成此数据? 调用代码Php MySQL性能-如何加速构建/烧毁图表的查询?,php,mysql,database-performance,Php,Mysql,Database Performance,我正在用MySQL/PHP编写一个应用程序生成构建图和一个燃尽图,我使用NVD3.js生成它 我下面的代码每天循环使用我的数据集的从最小到最大的日期,可以对其进行筛选 到目前为止,我每天运行查询1次,我意识到这会增加巨大的延迟,大约10秒等待加载 如何更快地生成此数据? 调用代码 public function burnupAction() { $actionItemTable = $this->getActionItemTable(); $burn
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;
}
for ($y = $minYear; $y <= $maxYear; $y++)
{
if ($y == $minYear)
$startMonth = $minMonth;
else
$startMonth = 1;
if ($y == $maxYear)
$finishMonth = $maxMonth;
else
$finishMonth = 12;
for ($m = $startMonth; $m <= $finishMonth; $m++)
{
if ($m < 10)
{
$month = "0$m";
}
else
{
$month = "$m";
}
$monthStr = $this->getMonth($m);
for ($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 * FROM actionitems " . $where;
if ($field == 'AssignedDate')
{
array_push($subsel, "(select '$dt' as AssignedDate, sum(case when AssignedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ECD')
{
array_push($subsel, "(select '$dt' as ECD, sum(case when ECD Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'DueDate')
{
array_push($subsel, "(select '$dt' as DueDate, sum(case when DueDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ClosedDate')
{
array_push($subsel, "(select '$dt' as ClosedDate, sum(case when ClosedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
}
}
}
if (count($subsel) == 0)
return array();
$sub = join(" union all ", $subsel);
if ($field == 'AssignedDate')
{
$sql = "select AssignedDate, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ECD')
{
$sql = "select ECD, NumActionItems as ECDItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'DueDate')
{
$sql = "select DueDate, NumActionItems as OriginalDueItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ClosedDate')
{
$sql = "select ClosedDate, NumActionItems as AcutalClosedItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
组合图表代码
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;
}
for ($y = $minYear; $y <= $maxYear; $y++)
{
if ($y == $minYear)
$startMonth = $minMonth;
else
$startMonth = 1;
if ($y == $maxYear)
$finishMonth = $maxMonth;
else
$finishMonth = 12;
for ($m = $startMonth; $m <= $finishMonth; $m++)
{
if ($m < 10)
{
$month = "0$m";
}
else
{
$month = "$m";
}
$monthStr = $this->getMonth($m);
for ($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 * FROM actionitems " . $where;
if ($field == 'AssignedDate')
{
array_push($subsel, "(select '$dt' as AssignedDate, sum(case when AssignedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ECD')
{
array_push($subsel, "(select '$dt' as ECD, sum(case when ECD Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'DueDate')
{
array_push($subsel, "(select '$dt' as DueDate, sum(case when DueDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ClosedDate')
{
array_push($subsel, "(select '$dt' as ClosedDate, sum(case when ClosedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
}
}
}
if (count($subsel) == 0)
return array();
$sub = join(" union all ", $subsel);
if ($field == 'AssignedDate')
{
$sql = "select AssignedDate, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ECD')
{
$sql = "select ECD, NumActionItems as ECDItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'DueDate')
{
$sql = "select DueDate, NumActionItems as OriginalDueItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ClosedDate')
{
$sql = "select ClosedDate, NumActionItems as AcutalClosedItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
for($y=$minYear;$y查询的主要部分如下:
SELECT 'Mar 01 2015' AS AssignedDate,
Sum(CASE
WHEN assigneddate BETWEEN '2015-03-01' AND '2015-03-01'
THEN 1
ELSE 0
end) AS 'NumActionItems'
FROM (SELECT *
FROM actionitems) s;
此查询有一个缺点:每个日期扫描表actionitems
为了改进这一点,可以将查询编写为:
SELECT 'Mar 01 2015' AS AssignedDate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-01';
这仍然不够完美,因此需要下一步:
所有日期的备选方案可以是:
SELECT assigneddate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-30'
GROUP BY assigndate;
这会给你每次约会的“裸体主义”
将@csum添加为外部查询:
SELECT assigneddate,
( @csum := @csum + numactionitems ) AS TotalActionItems
FROM ( SELECT assigneddate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-30'
GROUP BY assigndate) a
应该给出相同的结果
同时添加索引:
CREATE INDEX idx_ai_nn_1 ON actionitems(assigneddate);
如果您正在扫描表中的日期范围是我假设您有日期索引,则此索引将起作用。您可以做的是存储@csum值。您还可以在SQL中列出1或2个完整查询。我知道您的代码的作用,但在我的脑海中生成它并不是提供性能建议的最佳方法。请e following-感谢您的快速回复,我相信我还没有为我的查询设置索引,但如果这有帮助的话,我可以通过添加索引来加速。好的,我知道您做了什么。是的,这可以做得更快。索引将是一部分,另一部分是主查询。我将使用一个答案框来完成这一部分:请随意输入谢谢你的快速回复。让我们进行更改,我会向您汇报。另外,我的行数实际上是相反的,它远小于我生成的日期数。好的,1提示:对于数据库中没有数据的日期,这不会返回数据。所以当迭代这个集合时,要考虑到这一点。还要首先在mysql会话中检查您的查询结果和这些结果:如果其中有错误,可以节省您大量时间:)谢谢您的评论,我正在尝试让它生成所有没有任何值的日期,我认为这可能需要在代码中保留我的主循环。