首页 > 解决方案 > Laravel - 如何优化 MIN - MAX - orderBy 查询?

问题描述

我在 Laravel 中的代码是:

Car::selectRaw('*,
    MIN(car_prices.price) AS min_price,
    MAX(car_prices.price) AS max_price,
    MAX(car_prices.updated_at) AS latest_update')
->leftJoin('car_prices', 'car_prices.car_id', 'cars.id')
->groupBy('car_prices.car_id')
->orderBy('latest_update', 'desc')
->paginate(10);

在抛出错误之前需要很长时间才能运行:

超过 60 秒的最大执行时间

表中的记录数cars为 100,000 和 6,000,000 car_prices

表结构:

CREATE TABLE `cars` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=110001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

CREATE TABLE `car_prices` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `car_id` bigint(20) unsigned NOT NULL,
  `price` decimal(8,2) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `car_prices_car_id_foreign` (`car_id`)
) ENGINE=MyISAM AUTO_INCREMENT=5506827 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

查询:

select count(*) as aggregate
    from `cars`
    left join `car_prices`
    on `car_prices`.`car_id` = `cars`.`id`
    group by `car_prices`.`car_id`;

select *,
    MIN(car_prices.price) AS min_price,
    MAX(car_prices.price) AS max_price,
    MAX(car_prices.updated_at) AS latest_update from `cars`
    left join `car_prices`
    on `car_prices`.`car_id` = `cars`.`id`
    group by `car_prices`.`car_id`
    order by `latest_update` desc
    limit 10
    offset 0;

我该如何优化它?我应该缓存数据吗?还是有比这更好的查询?

标签: mysqllaravelquery-optimization

解决方案


您使用的查询不适用于如此大的表。相反,每当进入表car_prices的条目设置操作并获取最小值和最大值并将其存储在汽车表中时。或者你可以为此设置一个crone。


推荐阅读