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 - 使用大数据优化更新/插入查询的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

数据库插入数据或更新数据的时候反应很慢,怎么优化?

技术浅谈大数据量下数据库查询插入的优化

如何使用 Laravel 4.2 在单个查询(不是 for 查询循环)中批量插入或更新

MySQL 大数据量快速插入方法和语句优化

laravel怎么在中间表插入数据

MySql中LongText类型大字段查询优化