我遇到的问题是海量数据的表,每个表大约百万条,每天会生成一个表。
我查询的时候是这样写的 在foreach 循环里写sql语句:$tableArr是表数组,如果查询的是1到3号的数据 这个数组是
array([0]=>table_20101001,[1]=>table_20101002,[2]=>table_20101003)
foreach($tableArr AS $table)
{
$sqlCnt ="SELECT COUNT(*) FROM $table h"
." WHERE ". $where;
$total += $tabcnt[$table] = $this->_gdb -> fetchOne($sqlCnt);
}
这样写把每个表的记录数加起来,最后$total是总记录数用于分页
再下面也是循环写的:
foreach($tableArr AS $k => $table)
{
$cntArr[] = $tabcnt[$table];
$sqlT = "SELECT CONCAT(h.id,'-$table') AS it,FROM_UNIXTIME(h.time) AS fmtdate,h.src_ip,h.url,"
." (h.ul_flux + h.dl_flux) AS totalflux, h.user_id, h.rule_id FROM $table h"
." WHERE ".$where. " ORDER BY h.time DESC LIMIT $offset,".$limit; $data = $this->_gdb -> fetchAll($sqlT);
$res = array_merge($res, $data); $cnt = count($data);
$cnts += $cnt;
if ($cnts >= _DATA_PER_PAGE_LOG)
{
break;
}
else
{
$limit = _DATA_PER_PAGE_LOG - $cnt;
if ($cnt > 0 && $cnt <= _DATA_PER_PAGE_LOG)
{
$offset = 0;
continue;
}
else
{
$offset = (array_sum($cntArr)) - ($page-1)*_DATA_PER_PAGE_LOG;
$offset = $offset > 0 ? $offset : -$offset;
}
}
}
return $res;
}
不知道这么写的效率和用union联合的一条sql语句查询的效率哪个高?请高手赐教!
另外我写这段代码:
$cnt = count($data);
$cnts += $cnt;
if ($cnts >= _DATA_PER_PAGE_LOG)
{
break;
}
else
{
$limit = _DATA_PER_PAGE_LOG - $cnt;
if ($cnt > 0 && $cnt <= _DATA_PER_PAGE_LOG)
{
$offset = 0;
continue;
}
else
{
$offset = (array_sum($cntArr)) - ($page-1)*_DATA_PER_PAGE_LOG;
$offset = $offset > 0 ? $offset : -$offset;
}
}
的目的是减少循环时多个表之间的衔接问题,比如第一个表数据记录数不满足每页显示的数目那么第二表该从哪里(limit m,n)查起,大家有没有好的方法?
我查询的时候是这样写的 在foreach 循环里写sql语句:$tableArr是表数组,如果查询的是1到3号的数据 这个数组是
array([0]=>table_20101001,[1]=>table_20101002,[2]=>table_20101003)
foreach($tableArr AS $table)
{
$sqlCnt ="SELECT COUNT(*) FROM $table h"
." WHERE ". $where;
$total += $tabcnt[$table] = $this->_gdb -> fetchOne($sqlCnt);
}
这样写把每个表的记录数加起来,最后$total是总记录数用于分页
再下面也是循环写的:
foreach($tableArr AS $k => $table)
{
$cntArr[] = $tabcnt[$table];
$sqlT = "SELECT CONCAT(h.id,'-$table') AS it,FROM_UNIXTIME(h.time) AS fmtdate,h.src_ip,h.url,"
." (h.ul_flux + h.dl_flux) AS totalflux, h.user_id, h.rule_id FROM $table h"
." WHERE ".$where. " ORDER BY h.time DESC LIMIT $offset,".$limit; $data = $this->_gdb -> fetchAll($sqlT);
$res = array_merge($res, $data); $cnt = count($data);
$cnts += $cnt;
if ($cnts >= _DATA_PER_PAGE_LOG)
{
break;
}
else
{
$limit = _DATA_PER_PAGE_LOG - $cnt;
if ($cnt > 0 && $cnt <= _DATA_PER_PAGE_LOG)
{
$offset = 0;
continue;
}
else
{
$offset = (array_sum($cntArr)) - ($page-1)*_DATA_PER_PAGE_LOG;
$offset = $offset > 0 ? $offset : -$offset;
}
}
}
return $res;
}
不知道这么写的效率和用union联合的一条sql语句查询的效率哪个高?请高手赐教!
另外我写这段代码:
$cnt = count($data);
$cnts += $cnt;
if ($cnts >= _DATA_PER_PAGE_LOG)
{
break;
}
else
{
$limit = _DATA_PER_PAGE_LOG - $cnt;
if ($cnt > 0 && $cnt <= _DATA_PER_PAGE_LOG)
{
$offset = 0;
continue;
}
else
{
$offset = (array_sum($cntArr)) - ($page-1)*_DATA_PER_PAGE_LOG;
$offset = $offset > 0 ? $offset : -$offset;
}
}
的目的是减少循环时多个表之间的衔接问题,比如第一个表数据记录数不满足每页显示的数目那么第二表该从哪里(limit m,n)查起,大家有没有好的方法?
Select Max(ID) From (
Select ID From from Order By ID limit 90000,1
) As tmp
) limit 29;用这种模式做翻页应该效率会高一些
Select Max(ID) From (
Select ID From from Order By ID limit 90000,1
) As tmp
) limit 29;
用这种模式做翻页应该效率会为什么会高呢?
看起来是个log表, 可以考虑使用archive引擎, 当然前提是你不需要修改操作(log似乎应该不需要).
archive表不支持order by,而且select会做全表扫描,所以你的程序肯定需要调整.如果不能转archive表,需要看你的where情况才能做优化,
个人觉得使用union all应该差不多, 你可以测试一下啊后面一个问题,要是我坚决改掉需求,不做跨日期的分页........