Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
最佳实践php数组和RAM使用_Php_Mysql_Arrays_Memory - Fatal编程技术网

最佳实践php数组和RAM使用

最佳实践php数组和RAM使用,php,mysql,arrays,memory,Php,Mysql,Arrays,Memory,我有12个mysql db表,如表1、表2……表12。每个表有200000条记录。每个记录包括国家、用户类型、包列。我想得到3列以上的统计数据。要做到这一点,首先,我要创建数组。然后使用数组,我得到统计数据 for ($i=1; $i<=12; $i++) { $query="SELECT `country`, `usertype`, `package` FROM `table$i`"; $result=mysql_query($query); while ($row =

我有12个mysql db表,如表1、表2……表12。每个表有200000条记录。每个记录包括国家、用户类型、包列。我想得到3列以上的统计数据。要做到这一点,首先,我要创建数组。然后使用数组,我得到统计数据

for ($i=1; $i<=12; $i++)
{
   $query="SELECT `country`, `usertype`, `package` FROM `table$i`";
   $result=mysql_query($query);
   while ($row = mysql_fetch_assoc($result))
   {
      $country= $row['country'];
      $usertype= $row['usertype'];
      $package= $row['package'];

      $stat_array[$country][$usertype][$package]= 1 + $stat_array[$country][$usertype][$package]
   }
}

对于($i=1;$i这里的一个问题是,在同一个函数中,php不会删除变量分配的内存。因此,您会覆盖/创建一个新行

您需要在while循环结束时取消设置行、国家/地区、用户类型和包。这将有助于提高内存(至少在PHP5.3之前,我在遍历大量数据行时遇到过类似问题)。另一个问题是stat_arr变量,因为它会为数据库中3个字段的每个组合创建1个数组字段。最糟糕的情况是您有200000个条目。这本身将占用大量ram

此外,从我看到的情况来看,你只想数一数这3列。这可能会有不同的做法:

使用(我不知道您是如何调用ID/主字段的,因此我在以下代码中调用它ID):


这样,您就不必手动求和,但可以通过SQL(大多数情况下更有效)进行求和。

12个查询?请注意,
SQL
中有
UNION
命令。 试试这个:

for ($i=1; $i<=12; $i++)
   $query=($i>1?'UNION ALL ':'')."SELECT `country`, `usertype`, `package` FROM `table$i` ";
$result=mysql_query($query);
// other code below
for($i=1;$i1?'UNION ALL':'')“从'table$i`'中选择'country`、'usertype`、'package`”;
$result=mysql\u query($query);
//下面是其他代码

这一切都在查询中。下面的查询将为您提供每个国家/地区、用户类型和软件包的计数结果。显然,您可以使用循环创建12个表联合,但为了可读性,我总共写下了它

还要记住使用UNION ALL,而不仅仅是UNION。如果使用UNION,重复行将被丢弃,但如果表1中某个组的计数为100,而表2中同一个组的计数也为100,则需要返回100两次,因此总和为200。如果使用UNION,则会返回100次,并且总和显然也为100

SELECT SUM(cnt) as total, `country`, `usertype`, `package` FROM
(
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table1 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table2 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table3 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table4 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table5 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table6 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table7 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table8 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table9 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table10 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table11 GROUP BY `country`, `usertype`, `package`
    UNION ALL
    SELECT COUNT(country) as cnt, `country`, `usertype`, `package` FROM table12 GROUP BY `country`, `usertype`, `package`

) temp
GROUP BY `country`, `usertype`, `package`
另一方面:你不必这么做

$stat_array[$country][$usertype][$package]= 1 + $stat_array[$country][$usertype][$package];
您只需执行以下操作:

$stat_array[$country][$usertype][$package]++;
最后,如果您使用像您这样的多维数组,它必须在内部进行大量检查。简单地说,它将首先在数组中找到正确的国家,然后再生成另一个数组。它将在该数组中找到用户类型,然后在包的第三个数组中再次执行相同的操作

如果$country、$usertype和$package都是字符串,那么您可以更好地连接这些字符串并使用它们

$key = $country.'_'.$usertype.'_'.$package;
$stat_array[$key]++;

但我想这一切都取决于数据存储在数组中后要如何处理。如果只是打印总计数,您甚至不需要数组,而是直接在查询结果循环中打印。

它使用了多少RAM?您希望它减少多少?您尝试了什么?谢谢您的快速回复。我没有检查ram的使用情况。我需要一种让statistac使用更少ram的最佳方法。如果你没有检查使用情况,那么你怎么知道你是否做了一些事情来使用更少的ram?这不会解决内存问题,但会多次降低处理时间。不要使用UNION,而是UNION ALL。你想计算所有表中的所有记录。UNION将放弃在单独的表中重复行。迭代mysql结果集不会造成巨大的内存消耗,取消设置$row也不会帮助减少内存消耗。根据我在php 5.4之前使用php的经验,如果在下一行重用变量之前不取消设置,至少还有几个字节。我有一个few过去的内存泄漏很小(非常小),但当我遍历1-2百万行时,它累积到总内存泄漏数兆字节。(当我在循环结束时使用unset时,泄漏消失了).lol…我不认为这是有道理的,如果我太天真的话,对不起。每次迭代都会重新设置现有的变量,它是如何增加内存的?我过去有过内存泄漏(PHP5.2和5.3)在进行了几次测试并尝试unset之后,我发现当我在while循环结束时使用no unset时,$row部分就出现了问题。我知道这听起来不合逻辑(特别是在考虑垃圾收集应该如何工作时)但在当时,它是唯一有助于关闭几个小字节(2-7字节)的东西内存泄漏累积了超过几百万行的数据,导致了相当大的泄漏。也许其他人知道这种现象的原因。我很难相信这一点,我一直在使用5.3,并处理了2000万次结果迭代,我从来没有遇到过这个问题,也许你以不同的方式,例如,一个额外的函数调用对于每个迭代,传递引用..etcW它为什么会终止它?这就是union运算符的作用。这是在合理的行数下假设的,假设生成了正确的索引。在本例中,一个位于
国家
用户类型
$key = $country.'_'.$usertype.'_'.$package;
$stat_array[$key]++;