我的任务是制作一个网络应用程序来替换由于用户数量不断增加而一直被锁定的excel预订表。预订数据库(大约有一百种可能的资产)看起来像这样:
+--------------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+---------------+------+-----+---------+-------+
| ID | int(11) | NO | PRI | 0 | |
| bookedDate | date | YES | | NULL | |
| bookedBy | varchar(256) | YES | | NULL | |
| startDate | date | YES | | NULL | |
| endDate | date | YES | | NULL | |
| Equipment1 | varchar(512) | YES | | NULL | |
| Equipment2 | varchar(512) | YES | | NULL | |
| ... | | | | | |
| Equipment15 | varchar(512) | YES | | NULL | |
+--------------------+---------------+------+-----+---------+-------+
因此,用户可以在预订中预订最多15个资产,持续时间为1d-1Y。
在我的php页面上,显示视图(仅显示已预订的资产)如下所示:
<<< << < Prev week Bookings for week 49 - 2014 Next week > >> >>>
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
01/12/2014 02/12/2014 03/12/2014 04/12/2014 05/12/2014 06/12/2014 07/12/2014
---------------------------------------------------------------------------------
Eq1 | fred tom tom tom harry
Eq4 | tom tom frank
Eq66 | tom tom
...
Eq832| harry
这一切都有效,但页面很慢。 20-30秒生成一个包含约50个资产的页面 选择显示哪些资产(大约需要3秒)的代码是:
function read_Equipment($sDate,$eDate){
$query = mysql_query("SELECT Equipment1 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment2 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment3 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment4 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment5 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment6 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment7 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment8 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment9 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment10 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment11 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment12 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment13 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment14 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate' union
SELECT Equipment15 FROM oldDB WHERE startDate<'$sDate' AND endDate>'$eDate'
order by Equipment1")or die();
while($ad= mysql_fetch_array($query)){
if($ad['Equipment1'] != "")
{
$rdata[$ad['Equipment1']] = $ad['Equipment1'];
}
}
return($rdata);
}
获取每天代码(大约120毫秒,总共大约20秒)看起来像这样
function read_booking($equipment,$sDate,$eDate){
$query = mysql_query("SELECT * FROM oldDB WHERE startDate<'$sDate' AND endDate>='$eDate' AND (
Equipment1 = '$equipment' OR
Equipment2 = '$equipment' OR
Equipment3 = '$equipment' OR
Equipment4 = '$equipment' OR
Equipment5 = '$equipment' OR
Equipment6 = '$equipment' OR
Equipment7 = '$equipment' OR
Equipment8 = '$equipment' OR
Equipment9 = '$equipment' OR
Equipment10 = '$equipment' OR
Equipment11 = '$equipment' OR
Equipment12 = '$equipment' OR
Equipment13 = '$equipment' OR
Equipment14 = '$equipment' OR
Equipment15 = '$equipment'
)")or die();
$rdata = "";
while($ad = mysql_fetch_array($query)){
if($ad != "")
{
$rdata += $ad['ID']." - ";
}
}
return($rdata);
}
将所有内容放在一起的代码如下所示
//$time_i = time at start of the week
$tepp = read_Equipment($sDate,$eDate);
foreach($tepp as $time){
echo '<tr><th class="booking_time_th">' . $time . '</th>';
$i = 0;
while($i < 7){
$i++;
$msc=microtime(true);
$strtmp = read_booking($time,date('Y-m-d', $time_i+($i)*24*3600),date('Y-m-d', $time_i+($i-1)*24*3600));
echo '<td>'.(microtime(true)-$msc).'s<div class="booking_time_div">
<div class="booking_time_cell_div" id="div:' . $strtmp . '" onclick="void(0)">' . $strtmp. '</div></div></td>';
}
echo '</tr>';
}
echo '</table>';
microtimes就在那里跟踪进度并且不会影响总长度。
所以我的问题是我怎样才能更好地结合sql查询,这样就不会有数百个小查询(数百个,总共20到30秒)? 我应该更好地重新安排数据库吗?
答案 0 :(得分:0)
我个人会给每个资产一个'id'并将他们的表标记为资产。然后我会创建一个设备表,其中的第一列将是'asset_id'。 'asset_id'将是资产表中'id'列的外键。这将创建从特定资产到设备表中任意数量的行的链接 - 有效地消除了15件设备的当前限制。这是一个EAV表结构。
然后,我将使用Laravel 4中的Eloquent或CodeIgniter的ActiveRecord:https://ellislab.com/codeigniter/user-guide/database/active_record.html
考虑使用框架构建您的系统。
编辑:索引也会加快搜索速度。我会索引startDate,endDate和搜索中使用的任何字段(当前所有设备字段)。但请注意,虽然这会加快SELECT查询,但它会略微减慢对此表的INSERT查询速度。此外,如果您切换到如上所述的EAV结构,您可以索引更少的列,以实现相同,更快的结果。