简体   繁体   English

在php视图中合并MYSQL查询

[英]Combining MYSQL queries in php view

I was given the task of making a web app to replace an excel booking sheet that was constantly locked due to growing number of users. 我的任务是制作一个Web应用程序,以替换由于用户数量不断增加而不断锁定的excel预订表。 The booking database (of about a hundred possible assets) looks something like this: 预订数据库(约有一百种可能的资产)如下所示:

+--------------------+---------------+------+-----+---------+-------+
| 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    |       |
+--------------------+---------------+------+-----+---------+-------+

So users can book out up to 15 assets in a booking for a period of 1d-1Y. 因此,用户可以在1d-1Y的时间内预订多达15项资产。

On my php page the display view (only booked assets are shown) looks something like this: 在我的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

This all works but the page is very slow. 所有这些都可以,但是页面非常慢。 20-30 sec to generate a page with ~50 assets The code to pick which assets are displayed (takes about 3 sec) is: 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);
}

And getting each day code (takes about 120ms, and around 20s in total) looks like this 每天获取代码(大约需要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);
}

The code for putting it all together looks like this 将所有内容组合在一起的代码如下所示

//$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>';

The microtimes are just there to track the progress and dont affect the total length all that much. 上课时间只是在跟踪进度,不会对总时长产生太大影响。

So my question is how can I better combine the sql queries so that there are not hundred of little queries (hundreds at 0.1ms total 20-30s)? 因此,我的问题是如何更好地组合sql查询,以使没有几百个小查询(数百个0.1ms中的20-30s)? Should I be rearranging the database better? 我应该更好地重新排列数据库吗?

I would personally give each asset an 'id' and label their table as assets. 我个人会给每个资产一个“ id”,并将其表标记为资产。 Then I would create a equipment table and the first column in it would be 'asset_id'. 然后,我将创建一个设备表,其中的第一列为“ asset_id”。 'asset_id' would be a foreign key to the 'id' column in the assets table. “ asset_id”将是资产表中“ id”列的外键。 This creates a link from a particular asset to any number of rows in the equipment table- effectively removing the current limitation of 15 pieces of equipment. 这将创建从特定资产到设备表中任意数量行的链接,从而有效地消除了当前对15件设备的限制。 This is an EAV Table structure. 这是一个EAV表结构。

Then again, I would be using Eloquent from Laravel 4 or CodeIgniter's ActiveRecord : https://ellislab.com/codeigniter/user-guide/database/active_record.html 再说一次,我将使用Laravel 4或CodeIgniter的ActiveRecord中的Eloquent: https ://ellislab.com/codeigniter/user-guide/database/active_record.html

Consider building your systems utilizing a framework. 考虑使用框架构建系统。

Edit: Indexes will also speed up your searches. 编辑:索引也将加快您的搜索。 I would index the startDate, endDate, and any fields used in search (currently all equipment fields). 我将索引startDate,endDate和搜索中使用的任何字段(当前为所有设备字段)。 However, please note that while this will speed up SELECT queries it will slightly slow down the INSERT queries to this table. 但是,请注意,虽然这将加快SELECT查询的速度,但会稍微减慢对该表的INSERT查询。 Also, if you do switch over to an EAV structure like I described above you can index far fewer columns to achieve the same, faster result. 同样,如果您确实切换到如上所述的EAV结构,则可以索引更少的列,以实现相同,更快的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM