0

我遇到了一个问题,即使用 Laravel的 Maatwebsite 插件创建 XLS/XLSX 报告的时间很慢(大约 5-30、30-60 分钟,具体取决于报告的条件),这是很多时间!!。

通过网络搜索,我发现 Maatwebsite 使用 PHPExcel,如果在生成 XLS/XLSX 文件时有很多或寄存器,它会很慢并且会消耗内存。

检查时间,我发现由于嵌套的 foreach 循环,我的查询几乎呈指数增长,报告的基本生成是这样的:

$clients = Client::all(); // can change depending on conditions, worse case with all clients
Excel::create('Client Statement', function($excel) use ($clients) {
     $excel->sheet('Sheet 1', function($sheet) {
          $row = 1; // row number
          foreach($clients as $client) {
               $sheet->row($row++, [$client->data1,...,$client->dataN]);

               $charges = Charge::get_ByClient($client->id);

               foreach($charges as $charge) {
                    $sheet->row($row++, [$charge->data1,...,$charge->dataN]);

                    $payments = Payment::get_ByCharge($charge->id);

                    foreach($payments as $payment) {
                         $sheet->row($row++, [$payment->data1,...,$payment->dataN]);
                    }
               }
          }
     });
});

基本解释是:

  1. 获取所有客户
  2. 为每位客户收取所有费用
  3. 对于每笔费用,获得所有付款

问题是,我有大约 1500 个客户,每个客户可以有 10 - 100 笔费用,每笔费用可以有 1 - 5 笔付款,这会导致性能下降。为此,将库生成 XLS/XLSX 文件所需的时间相加。

有什么建议么?提前致谢。

4

2 回答 2

1

如果我理解正确的话。您可以使用以下示例。效果很好。取自 http://www.websleson.info/2016/02/ex

创建 MYSQL 表

CREATE TABLE IF NOT EXISTS `tbl_customer` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `CustomerName` varchar(50) NOT NULL,
  `Address` varchar(50) NOT NULL,
  `City` varchar(50) NOT NULL,
  `PostalCode` int(12) NOT NULL,
  `Country` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;


INSERT INTO `tbl_customer` (`id`, `CustomerName`, `Address`, `City`, `PostalCode`, `Country`) VALUES
(1, 'Maria Anders', 'Obere Str. 57', 'Berlin', 12209, 'Germany'),
(2, 'Ana Trujillo', 'Avda. de la Construction 2222', 'Mexico D.F.', 5021, 'Mexico');

索引.PHP

<?php
$connect = mysqli_connect("localhost", "root", "", "testing");
$sql = "SELECT * FROM tbl_customer";  
$result = mysqli_query($connect, $sql);
?>
<html>  
 <head>  
  <title>Export MySQL data to Excel in PHP</title>  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />  
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>  
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>  
 </head>  
 <body>  
  <div class="container">  
   <br />  
   <br />  
   <br />  
   <div class="table-responsive">  
    <h2 align="center">Export MySQL data to Excel in PHP</h2><br /> 
    <table class="table table-bordered">
     <tr>  
                         <th>Name</th>  
                         <th>Address</th>  
                         <th>City</th>  
       <th>Postal Code</th>
       <th>Country</th>
                    </tr>
     <?php
     while($row = mysqli_fetch_array($result))  
     {  
        echo '  
       <tr>  
         <td>'.$row["CustomerName"].'</td>  
         <td>'.$row["Address"].'</td>  
         <td>'.$row["City"].'</td>  
         <td>'.$row["PostalCode"].'</td>  
         <td>'.$row["Country"].'</td>
       </tr>  
        ';  
     }
     ?>
    </table>
    <br />
    <form method="post" action="export.php">
     <input type="submit" name="export" class="btn btn-success" value="Export" />
    </form>
   </div>  
  </div>  
 </body>  
</html>

EXSPORT.PHP

<?php  
//export.php  
$connect = mysqli_connect("localhost", "root", "", "testing");
$output = '';
if(isset($_POST["export"]))
{
 $query = "SELECT * FROM tbl_customer";
 $result = mysqli_query($connect, $query);
 if(mysqli_num_rows($result) > 0)
 {
  $output .= '
   <table class="table" bordered="1">  
                    <tr>  
                         <th>Name</th>  
                         <th>Address</th>  
                         <th>City</th>  
       <th>Postal Code</th>
       <th>Country</th>
                    </tr>
  ';
  while($row = mysqli_fetch_array($result))
  {
   $output .= '
    <tr>  
                         <td>'.$row["CustomerName"].'</td>  
                         <td>'.$row["Address"].'</td>  
                         <td>'.$row["City"].'</td>  
       <td>'.$row["PostalCode"].'</td>  
       <td>'.$row["Country"].'</td>
                    </tr>
   ';
  }
  $output .= '</table>';
  header('Content-Type: application/xls');
  header('Content-Disposition: attachment; filename=download.xls');
  echo $output;
 }
}
?>
于 2017-05-05T19:30:46.607 回答
0

只是为了澄清这一点,我确实使用了 @Mark Ba​​ker 建议的 Eloquent 的关系来加快速度,我的问题是典型的 N + 1 问题。为了解决这个问题,我使用了 Laravel 的 Eager Loading

于 2017-08-29T03:33:21.240 回答