Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP:Laravel查询优化_Php_Mysql_Database_Laravel 5_Optimization - Fatal编程技术网

PHP:Laravel查询优化

PHP:Laravel查询优化,php,mysql,database,laravel-5,optimization,Php,Mysql,Database,Laravel 5,Optimization,我有一个query,即通过一个包含30多万条记录的表进行查询。下面是Laravel 5.5中的查询: $this->select = \DB::table('transport_orders') ->join('users', 'users.id', '=', 'transport_orders.user_id', 'left') ->join('transport_order_price_requests', 'transport_order_price_requ

我有一个
query
,即
通过一个包含30多万条记录的表进行查询。下面是Laravel 5.5中的查询:

$this->select = \DB::table('transport_orders')
   ->join('users', 'users.id', '=', 'transport_orders.user_id', 'left')
   ->join('transport_order_price_requests', 'transport_order_price_requests.transport_order_id', '=', 'transport_orders.id', 'left')
   ->join('price_requests', 'transport_order_price_requests.price_request_id', '=', 'price_requests.id', 'left')
   ->join('order_numbers', 'transport_orders.order_number_id', '=', 'order_numbers.id', 'left')
   ->join(\DB::raw('
                (select transport_order_statuses.transport_order_id, max(transport_order_statuses.id) as last_link_id
                from transport_order_statuses
                group by transport_order_statuses.transport_order_id) as last_statuses'
            ), function ($join) {
     $join->on('transport_orders.id', '=', 'last_statuses.transport_order_id');
            })
   ->join('transport_order_statuses', 'last_statuses.last_link_id', '=', 'transport_order_statuses.id')
   ->join('statuses', 'transport_order_statuses.status_id', '=', 'statuses.id')
   ->select(
        'transport_orders.id as id',
             \DB::raw('CONCAT(users.first_name, \' \', users.last_name) as user_full_name'),
              \DB::raw('DATE_FORMAT(transport_orders.pickup_date , "%Y-%m-%d") as pickup_date'),
         'transport_orders.location_name',
         'transport_orders.carrier_name',
         'transport_orders.country_name',
         'transport_orders.country_code',
         'transport_orders.category_name',
         'transport_orders.zip',
         'transport_orders.rate_type',
         'transport_orders.rate_name',
         'transport_orders.order_number_id',
         'order_numbers.order_number as order_number',
         'transport_orders.comment',
         'transport_orders.inbound',
         'transport_orders.unit',
         'transport_orders.unit_value',
         \DB::raw('DATE_FORMAT(transport_orders.created_at , "%Y-%m-%d") as created_at'),
         'transport_orders.base_price',
         'transport_orders.created_at',
         'transport_orders.updated_at',
         'transport_orders.price',
         'transport_orders.stops',
         'transport_orders.stop_price',
         'transport_orders.id as id',
         'transport_orders.transport_mode as transport_mode_name',
         'statuses.status as status',
         'statuses.id as status_id',
         'transport_orders.multishipment as multishipment',
         'transport_orders.total_weight as total_weight',
         'order_numbers.simulation as simulated'
 )->where('transport_orders.is_deleting', '=', 0);
在此之后,我会:

$this->select->paginate($itemsPerPage);
现在,如果要将此
查询
转换为普通的
MySql
,那么它就是:

select  `transport_orders`.`id` as `id`,
CONCAT(users.first_name, ' ', users.last_name) as user_full_name,
DATE_FORMAT(transport_orders.pickup_date , "%Y-%m-%d") as pickup_date,
`transport_orders`.`location_name`, `transport_orders`.`carrier_name`,
`transport_orders`.`country_name`, `transport_orders`.`country_code`,
`transport_orders`.`category_name`, `transport_orders`.`zip`,
`transport_orders`.`rate_type`, `transport_orders`.`rate_name`,
`transport_orders`.`order_number_id`, `order_numbers`.`order_number` as `order_number`,
`transport_orders`.`comment`, `transport_orders`.`inbound`, `transport_orders`.`unit`,
`transport_orders`.`unit_value`,
DATE_FORMAT(transport_orders.created_at , "%Y-%m-%d") as created_at,
`transport_orders`.`base_price`, `transport_orders`.`created_at`,
`transport_orders`.`updated_at`, `transport_orders`.`price`, `transport_orders`.`stops`,
        `transport_orders`.`stop_price`, `transport_orders`.`id` as `id`,
        `transport_orders`.`transport_mode` as `transport_mode_name`,
        `statuses`.`status` as `status`, `statuses`.`id` as `status_id`,
        `transport_orders`.`multishipment` as `multishipment`,
        `transport_orders`.`total_weight` as `total_weight`, `order_numbers`.`simulation` as `simulated`
    from  `transport_orders`
    left join  `users`  ON `users`.`id` = `transport_orders`.`user_id`
    left join  `transport_order_price_requests`  ON `transport_order_price_requests`.`transport_order_id` = `transport_orders`.`id`
    left join  `price_requests`  ON `transport_order_price_requests`.`price_request_id` = `price_requests`.`id`
    left join  `order_numbers`  ON `transport_orders`.`order_number_id` = `order_numbers`.`id`
    inner join  
    (
        SELECT  transport_order_statuses.transport_order_id, max(transport_order_statuses.id) as last_link_id
            from  transport_order_statuses
            group by  transport_order_statuses.transport_order_id
    ) as last_statuses  ON `transport_orders`.`id` = `last_statuses`.`transport_order_id`
    inner join  `transport_order_statuses`  ON `last_statuses`.`last_link_id` = `transport_order_statuses`.`id`
    inner join  `statuses`  ON `transport_order_statuses`.`status_id` = `statuses`.`id`
    where  `transport_orders`.`is_deleting` = 0
      and  `order_numbers`.`simulation` = 0
    order by  `transport_orders`.`created_at` desc
    limit  13 offset 0

Laravel
debugbar
告诉我查询花费的时间超过了9秒。当我使用
paginate
Length-Aware-Paginator
)时,它也会进行计数,因此需要大约6秒的时间。当我在
MySql
中运行普通查询时,也需要9-10秒。如何优化此查询?请注意,我不想使用
simplePaginate
,因为它需要大量重构。

这些索引可能会有帮助:

transport_order_statuses:  (transport_order_id, id)
transport_orders:  (is_deleting, created_at)
transport_order_price_requests:  (transport_order_id, price_request_id)
将所有
左连接
更改为
连接
可以提供相同的答案,同时为优化器提供更多选项(并减少混淆)

由于在
WHERE
中引用了两个表,因此在通过
LIMIT
获得
订单之前,可能必须通过
WHERE
完成查询评估,因此不允许在此区域进行任何优化。去除
simulation=0
可能会加快速度(以获取太多行为代价)。

只是为了观察,日期是“%Y-%m-%d”,因此日期格式(…%Y-%m-%d”)要么是冗余的,要么是与日期相同的(…)