PHP和MYSQL-100000+行140+列-如果循环50+查询-找到更好的方法

PHP和MYSQL-100000+行140+列-如果循环50+查询-找到更好的方法,php,mysql,optimization,for-loop,Php,Mysql,Optimization,For Loop,我有一个数据库,包含约100000行和约150列数据,格式如下: data_id data_name monthly_data1 monthly_data2 monthly_data3 "" "" 0 product1_data-item1 20 30 10 "" "" 1 product1 data-item2

我有一个数据库,包含约100000行和约150列数据,格式如下:

data_id               data_name  monthly_data1  monthly_data2  monthly_data3    ""    ""
      0     product1_data-item1             20             30             10    ""    ""
      1     product1 data-item2             10             30             20    ""    ""
      2     product1 data-item3              9             10             23    ""    ""
      3     product2 data-item1             40             13             12    ""    ""
      4     product2 data-item2             31             12             32    ""    ""
      5     product2 data-item3             23             49             23    ""    ""
上述数据集是数据的基本样本,实际上,有2000多个产品,其中50多个数据项,每个约100000行,约140列数据为年度数据

我需要在数据库中搜索每个数据项-每个产品,即每行,并确定每个数据项的month_data1到month_data140列中的值是否在该特定数据项的预定最小/最大范围内

这是我的代码的格式,它正在工作,只是非常缓慢,大约20秒来完成每年每个产品的所有50次检查

$numberProducts = 2000;
$numberLineItems = 50;
$numberMonths = 140;

for($m=0;$m<$numberMonths;$m++){
    for($p=0;$p$numberProducts;$p++){
      $dataMonth = 'data_month'.$m+1;
          $q="SELECT $dataMonth FROM product_table WHERE data_id='".($p*$numberLineItems)."'";
          $q=mysql_query($q);
          while($row=mysql_fetch_assoc($q)){
              $dataVal = $row[$dataMonth];
          }
          mysql_free_result($q);
          if(($dataVal>=$dataMin1)&&($dataVal<=$dataMax1)){
              $q="SELECT $dataMonth FROM product_table WHERE data_id='".($p*$numberLineItems+1)."'";
              $q=mysql_query($q);
              while($row=mysql_fetch_assoc($q)){
                  $dataVal = $row[$dataMonth];
              }
              mysql_free_result($q);
              if(($dataVal>=$dataMin2)&&($dataVal<=$dataMax2)){
                  $q="SELECT $dataMonth FROM product_table WHERE data_id='".($p*$numberLineItems+2)."'";
                  $q=mysql_query($q);
                  while($row=mysql_fetch_assoc($q)){
                      $dataVal = $row[$dataMonth];
                  }
                  mysql_free_result($q);
                  if(($dataVal>=$dataMin3)&&($dataVal<=$dataMax3)){
.
.
.
等等。一直到每月每个产品的第50个数据项,检查该产品的该数据项的月值是否在预定范围内。每个产品的每个单独数据项的预定范围dataMin/dataMax不同,但每个产品之间的特定数据项相同

我正在寻找一种方法来加速代码、不同的查询组合、服务器设置、循环样式等,这可能有助于优化事情,并使输出只需要几秒钟。任何想法都将不胜感激

我的第一个想法是更改select语句以选择整个数据库 $q=从product_表中选择*; 并将数据放入多维数组中,以进行最小/最大检查,避免14000000次查询,但我遇到了内存不足的限制


必须有更好的方法…

您可以尝试,如下所示。。。我发送未经测试,如果您发现任何语法错误,请尝试更正这些语法错误

 $numberMonths = 140;
 $minRange = 20;
 $maxRange = 35;
 $dataItemArray = array();

 $q=mysql_query("SELECT * FROM product_table");
 while($row=mysql_fetch_assoc($q)){
         for($i = 1 ; $i <= numberMonths; $i++){
            $nowColumn = monthly_data$i;
            if(($row[$nowColumn] >= $minRange) AND ($row[$nowColumn] <= $maxRange))
                $dataItemArray = $row['data_name']
         }  

      }

以下是一种方法:

for ($i = 1; $i <= 50; $i++) {

    $$min = 'dataMin' . $i;
    $$max = 'dataMax' . $i;

    $dataMonth = 'data_month' . $i;

    //Query to get all the data_id's that fall in the given range
    //If you know that many of your data_month values will be in the min max range, 
    //you can use the opposite of this query.
    //i.e select those data_ids that are not in the range -- this result set 
    //will be significantly smaller and will consume much less time and memory
    /*
     * eg: 
     * $res = mysql_query('SELECT data_id 
                            FROM product_table 
                            WHERE ' . $dataMonth . ' > ' . $$max . ' OR ' . $dataMonth . ' < ' . $$min);
     */
    $res = mysql_query('SELECT data_id 
                            FROM product_table 
                            WHERE ' . $dataMonth . ' <= ' . $$max . ' AND ' . $dataMonth . ' >= ' . $$min);
    if (mysql_num_rows($res) > 0) {
        while ($row = mysql_fetch_assoc($res)) {
            //this arr will contain the data_ids who are in the given range for the moth $dataMonth
            $finalArr[$dataMonth][] = $row['data_id'];
        }
    }
    mysql_free_result($res);
    //$finalArr will have months as keys and data_ids who have the value in the specified range
}

一次性获取整个范围的结果,然后进行分析?从product_表中选择data_id,$dataMonth,其中data_id介于:min_id和:max_id之间。哦,还有。这是一个很好的例子,如果您将每个月放在单独的列中,$i来自何处,可能会发生什么?您是否考虑过规范化架构,以便每行都保存单个月/数据项的数据?这样做无疑会简化和优化代码的速度。如果这是一个选项,我相信我们可以为新设计提供建议。@IIIOXIII最有可能,是的,因为你可以很容易地在一列上创建索引,但是140个索引,我猜增长不容易维护,也不容易让查询优化器使用。不起作用。正如我在第一篇文章中所说的,我已经尝试过了,选择14000000个单元格1000000行*14000列,脚本的内存就用完了。请给出您的反馈?感谢你的反馈?请给出您对以上内容的看法,因为这有助于社区知识的增长。谢谢