【问题标题】:Import Excel into mySQL taking too long将 Excel 导入 mySQL 耗时太长
【发布时间】:2018-08-08 22:08:56
【问题描述】:

所以,我有一个表单,允许用户上传 Excel 工作表,然后系统会将 Excel 数据导入 mySQL。

但是,每次我使用 AJAX 提交表单时,它都会启动进程,保存大约一半的数据,然后给我一个 504 网关错误。我已经将 PHP 配置超时更改为 300,但它仍然在中途放弃。我不认为 1000 行以下的 Excel 工作表应该花费 5 分钟以上的时间?

这是我的代码:

 public function postImportGroup(Request $request)
{

    if($request->hasFile('import_numbers')) {
       $file = $request->file('import_numbers');
       $file_extension = Input::file('import_numbers')->getClientOriginalExtension();
       $supportedExt = array('csv', 'xls', 'xlsx');

    if (!in_array_r($file_extension, $supportedExt)) {
        return response()->json([
            'status' => 'error',
            'msg' => 'Please make sure that the uploaded file is a valid CSV, XLS, XLSX sheet.',
        ]);
    }

   }

    $results = Excel::load($file)->get();

    $results = json_decode($results[0], true);

    $class = new DailyGroup();
    $class->title = $request->group_name;
    $class->user_id = Auth::guard('client')->user()->id;
    $class->entries = count($results);
    $class->save();

    foreach ($results as $r => $value) {
      //$data = array_values($value);
        //return $value["employee_number"];
      $group = new DailyGroupLocations();

      $address = $value["address"] . ',' . $value["city"] . ',' . $value["state"] . ',' . $value["zip"];
      $c = $value["country"];

      $file_contents = file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode($address) . '&components=country:' . urlencode($c) .'&sensor=false&key=xxx');
      $json_decode = json_decode($file_contents);


      if (isset($json_decode->results[0])) {  
        $group->lat = $json_decode->results[0]->geometry->location->lat;
        $group->lng = $json_decode->results[0]->geometry->location->lng;
    }
      $phone = preg_replace('/\D+/', '', $value["ph"]);
      $phone = '1'.$phone;

      $group->user_id = Auth::guard('client')->user()->id;
      $group->group_id = $class->id;
      $group->employee_number = $value["employee_number"];
      $group->work_date = $value["work_date"]["date"];
      $group->first_name = $value["name"];
      $group->last_name = $value["lastname"];
      $group->phone = $phone;
      $group->email = $value["email"];
      $group->job_number = $value["job_number"];
      $group->address = $value["address"];
      $group->city = $value["city"];
      $group->state = $value["state"];
      $group->zip = $value["zip"];
      $group->country = $value["country"];
      $group->job_name = $value["job_name"];
      $group->location = $value["location"];
      $group->shift_description = $value["shift_description"];
      $group->shift_start = $value["shift_start_time"];
      $group->shift_end = $value["shift_end_time"];
      $group->post_hours = $value["post_hours"];
      $group->save();
}

        return response()->json([
            'status' => 'success',
            'msg' => 'All data uploaded successfully. Please wait for tables to refresh.',
            //'url' => '/user/location/location-areas'
        ]);
}

我可以做些什么来优化它吗?我在 foreach 语句中有很多事情吗?我可以使用任何提示或技巧吗?

【问题讨论】:

  • 减速在哪里?代码并没有告诉我们太多关于数据库层或 save() 如何操作的信息。是对 Google 的地理编码调用吗? 1000 行,每个对 google 的请求 1 秒...加起来。我将其作为一项工作运行,而不是让用户/客户端在整个过程中都处于困境中。
  • 你认为这可能是谷歌的电话吗?我将禁用呼叫并测试它是否变得更快。
  • @ficuscr 好的,所以这绝对是谷歌的电话。刚查了一下。就将它作为一项工作运行而言,我是每分钟调用一次还是每 10 分钟调用一次?你能指引我正确的方向吗?
  • 作业队列有很多方法。 RabbitMQ 每隔一段时间就会启动一个脚本。是的,一个简单的方法是每 10 分钟触发一个脚本,寻找要处理的东西。添加一些登录以供用户获得反馈。等如果您不需要超精确的纬度/经度数据,则将其基于他们的邮政编码。无论如何,谷歌一直在提高利率:)
  • 知道了。感谢您的建议,看看它会如何运作。 @ficuscr

标签: php mysql laravel


【解决方案1】:

它不是 excel 文件花时间......它是阻止您的代码执行的谷歌地理编码调用。

您可以为自己获取一个 google api 密钥来加快您的流程。

参考:https://developers.google.com/maps/documentation/javascript/get-api-key

您还应该检查地理编码调用的响应状态

$status = json_decode->results[0]->status;

可能的状态值:

  • 好的
  • 零结果
  • OVER_QUERY_LIMIT
  • INVALID_REQUEST
  • UNKNOWN_ERROR

如果可能的话,您可以考虑对数据集进行预地理编码,将 lat 和 lng 值与地址一起存储,这样如果您期望或需要快速执行,就不必即时进行地理编码。

【讨论】:

  • FYI:“所有 Google Maps Platform API 请求都必须包含 API 密钥;我们不再支持无密钥访问。”
  • @ficuscr 来自 google 的此声明不适用于地理编码。
  • 源链接在评论中仅供参考:在这里,developers.google.com/maps/documentation/geocoding/… 您的链接已过时。现在必须启用计费并使用 API 密钥。
  • @ficuscr 你是完全正确的......直到今天一切都在现场工作......但现在我急于应用身份验证密钥!
  • 几天前是我 :) 一定要设置每日配额以避免意外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
  • 2011-02-07
相关资源
最近更新 更多