我有一个数据库,其中包含~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+ 个数据项(约 100,000 行)和大约 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_table中选择*";并将数据放入多维数组中以进行最小/最大检查并避免 14,000,000 次查询,但我遇到了"内存不足"限制。
一定有更好的方法...
你可以试试,就像下面一样...我正在发送没有测试,如果您发现任何语法错误,请尝试更正这些语法错误......
$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
}