데이터 대량 Insert Or Update 방법에 관한 고찰 - Migration And Seeder 사용하기

 

 데이터 대량 Insert Or Update 방법에 관한 고찰

  • 개발자가 새로운 프로젝트만 개발하면 좋겠지만, 운영팀에서 종종 Data 관련 대량 작업을 요구할 때가 있습니다.
  • db관련 작업만 insert or update 하는것이라면 sql문법으로 쿼리실행만 해주면 되지만 Input시 observer 작업 혹은
  • API까지 동시에 처리해주어야 한다면 이건 꽤나 골치아픕니다.
  • 본인의 경우 아래와 같은 작업으로 작업을 진행하는데 더 좋은 방법이 있다면 댓글로 알려주시면 감사하겠습니다.

 

1. DB Query문 짜기

  • 예시로 products table에 있는 1~5000 까지의 id값에 해당하는 컬럼 몇가지를 update 하는 요청이 들어옵니다.
  • 각 row당 barcode,box_width,box_length,box_height,box_volume에 대한 값들을 update하는 쿼리를 작성합니다.
UPDATE products SET  barcode='100000', box_width='8', box_length='15', box_height='4', box_volume='81' WHERE id='1';
UPDATE products SET  barcode='100001', box_width='9', box_length='16', box_height='3', box_volume='79' WHERE id='2';
UPDATE products SET  barcode='100002', box_width='9', box_length='16', box_height='3', box_volume='86' WHERE id='3';
UPDATE products SET  barcode='10003', box_width='9', box_length='16', box_height='3', box_volume='72' WHERE id='4';
UPDATE products SET  barcode='10004', box_width='9', box_length='15', box_height='7', box_volume='189' WHERE id='5';
UPDATE products SET  barcode='10005', box_width='10', box_length='12', box_height='4', box_volume='96' WHERE id='6';
UPDATE products SET  barcode='10006', box_width='10', box_length='12', box_height='7', box_volume='156' WHERE id='7';
UPDATE products SET  barcode='10007', box_width='10', box_length='12', box_height='7', box_volume='156' WHERE id='1000';
UPDATE products SET  barcode='10008', box_width='12', box_length='11', box_height='4', box_volume='88' WHERE id='1001';
UPDATE products SET  barcode='10009', box_width='13', box_length='14', box_height='13', box_volume='456' WHERE id='1002';
UPDATE products SET  barcode='20000', box_width='14', box_length='14', box_height='14', box_volume='510' WHERE id='1003';
UPDATE products SET  barcode='200001', box_width='15', box_length='12', box_height='11', box_volume='380' WHERE id='1004';
UPDATE products SET  barcode='300000', box_width='15', box_length='15', box_height='13', box_volume='566' WHERE id='4999';
UPDATE products SET  barcode='500000', box_width='16', box_length='8', box_height='4', box_volume='87' WHERE id='5000';
  • 해당쿼리를 localhost db에 dump한 스키마에서 실행해봅니다.
  • 잘 적용되는 것 까지 확인합니다.

 

2. Migration 및 seeder를 활용한 Update 작업 후처리(API 등)

  • 상품정보를 관계사에 넘겨주는 작업을 해야 할 때가 있다고 가정합니다.
  • migration 파일, seeder 파일을 생성하고 migration에서 seeder를 실행할수 있게 합니다.
# migration 파일 생성
$ php artisan make:migration send_data_from_products_table_to_api

# seeder 생성
$ php artisan make:seeder Send_data_from_products_table_to_API_Seeder


# send_data_from_products_table_to_api.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class SendDataFromProductsTableToApi extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // migration 파일 실행시 artisan 명령어를 사용하여 SendDataFromProductsTableToApiSeeder를 실행하겠다. 
        Artisan::call('db:seed', ['--class' => 'SendDataFromProductsTableToApiSeeder', '--force' => true]);
        
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {

    }
}
  • SendDataFromProductsTableToApiSeeder.php 에서 아래와 같이 후처리를 해줍니다.
# SendDataFromProductsTableToApiSeeder.php

<?php

use Illuminate\Database\Seeder;

use App\Product;
use App\UseApi;

class SendDataFromProductsToDeleoApi2Seeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
		// 1부터 5000까지 상품 콜렉션을 가져온다
        $products = Product::whereBetween('id',[1,5000])->get();

        foreach ($products as $product) {
        	//1에서 update한 상품들을 data에 담는다.
            $data = [
                'barcode' => (string)$product->barcode,
                'box_width' => (string)$product->box_width,
                'box_length' => (string)$product->box_length,
                'box_height' => (string)$product->box_height,
                'box_volume' => (string)$product->box_volume,
            ];
			
            //필요한 API에 송출해준다.
            UseApi::editProduct($data, $product->id);
            usleep(100000); // API 발송 텀을 두기 위해 0.1초 딜레이
        }
    }
}

 

 

마무리

  • 위 작업 완료 후 , 로컬에서 migration 파일을 실행해 본 후, 잘 작동한다면 서버에 배포하는 형식으로 사용합니다.