Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?
Posted
技术标签:
【中文标题】Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?【英文标题】:Laravel - What is the best approach to optimize update/insert queries with large data?Laravel - 使用大数据优化更新/插入查询的最佳方法是什么? 【发布时间】:2020-06-30 07:29:20 【问题描述】:有超过 200 个用户登录。每个用户每 15 分钟在与父表 cars
相关的子表 car_prices
中插入/更新 1000 条记录。
CREATE TABLE `cars` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB 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=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
用户每 15 分钟执行一次此查询(例如):
INSERT INTO `car_prices` VALUES(NULL, 1, 3000, NOW(), NOW())
INSERT INTO `car_prices` VALUES(NULL, 2, 7000, NOW(), NOW())
INSERT INTO `car_prices` VALUES(NULL, 3, 5000, NOW(), NOW())
// ...and many other inserts approximately 1000
或
UPDATE `car_prices` SET `price` = 4000 WHERE `id` = 1;
UPDATE `car_prices` SET `price` = 8000 WHERE `id` = 2;
UPDATE `car_prices` SET `price` = 6000 WHERE `id` = 3;
// ...and many other updates approximately 1000
我该如何克服这个问题?有很多数据,更新/插入需要很长时间。我应该做一些 mysql 可能具有的特殊功能吗?或者模式可能是错误的?或者我应该使用 Laravel 可能具有的一些功能?
【问题讨论】:
你想克服什么问题? @Strawberry 更新/插入需要很长时间。 您应该分块插入数据(分块发送 SQL 命令,而不是一一发送)。我无法提供任何代码,因为我不知道您插入的完整上下文(数据来自何处、如何存储等) 中间的 14 分钟用户在做什么? @Strawberry 什么都没有。但我计算出用户几乎每 15 分钟插入/更新一次。 【参考方案1】:您可以使用块以更有效的方式执行此任务
查看我用于同步我的表产品的日常 cron 作业的这个示例
DB::beginTransaction();
try
$response = json_decode(file_get_contents('API_URL_GOES_HERE'), true);
if(!empty($response['products']))
$tempArr = [];
foreach ($response['products'] as $product)
$tempArr[] = [
'name' => $product['name'],
'price' => $product['price'],
'category_id' => $product['category_id'],
];
Product::truncate();
$insertData = collect($tempArr);
$chunks = $insertData->chunk(500);
foreach ($chunks as $chunk)
Product::insert($chunk->toArray());
DB::commit();
dd($countProducts . ' Products imported successfully.');
else
dd('No products to import were found.');
catch(\Exception $e)
DB::rollback();
$this->info('');
dump('Import failed : ' . $e->getMessage());
dd('DB rolled back.');
【讨论】:
以上是关于Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章