AWS

[AWS S3] object 여러 건 삭제 요청

girin_dev 2022. 7. 15. 13:26
728x90
반응형

목적 : 

 

삭제 총 타겟 : DB상에 있는 데이터 기준으로 1억 8천만 건에 해당. 

 

 

JAVA 에서 aws SDK 를 이용한 삭제 요청시에는 1회 요청 최대 오브젝트 수가 1000개로 제한되어있음. 

 

 

따라서 비동기방식으로 DB의 데이터를 1000건씩 조회 해서 삭제 요청을 계속 던지는 쓰레드를 구현 하려 함. 

 

 

controller : 

@ApiOperation(value = "aws s3 object delete api", notes = "")
    @RequestMapping(value = "/del/{offset}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> s3DeleteObjList(
            @RequestParam("offset") String _offset
    ) {
        try {

            log_demo.info("run..!");

            // 삭제 할 전체 데이터의 총량 체크
            int allCount = jdbcTemplate.queryForObject(
                        "select count(*)" +
                            " from bc_media as m" +
                            " join bc_scene as s on m.media_id = s.media_id" +
                            " where m.media_type = 'proxy'"
                        , Integer.class);

            ExecutorService executorService = Executors.newFixedThreadPool(4);

            boolean flag= false;

            if (_offset!=null && "".equalsIgnoreCase(_offset)) {
                offset = Integer.parseInt(_offset);
            }

            while(offset < allCount){
                for (int i = 0; i <4; i ++ ) {
                    Thread.sleep(100);
                    executorService.submit(() -> {
                        offset+=1000;
                        ThreadRunner(allCount, offset);
                    });
                }

                if (executorService.isTerminated() || executorService.isShutdown()) {
                    log_demo.info(" 쓰레드 종료.");
                }

            }

        } catch (Exception e) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            PrintStream pinrtStream = new PrintStream(out);
            e.printStackTrace(pinrtStream);
            System.out.println(out);
            return new ResponseEntity<>( HttpStatus.INTERNAL_SERVER_ERROR);
        } finally {
            System.out.println(" 끝남...?");
        }
        return new ResponseEntity<String>("SUCCESS!!!", HttpStatus.OK);
    }

 

 

 

 

Thread :  4개로 돌리면 대충 걸리는 시간 1000건 당 80초 정도 소요된다 치면 2~3달 정도 잡고 돌릴 예정임.

 

 

*****

 

22 08 11 수정 offset 쿼리의 단위가 커질 수록 성능 이슈가 있다 5000만이 offset에 걸린다면, 

 

5000만 건을 읽고 버린뒤에 1000건을 쓰는 방식이므로,  좋지 않은 방식이다. 

 

*****

 

그림과 같은 문제점이 생김.

 

 

수정한 쿼리의 실행계획 중 Extras 의 Using index 를 볼 때에 ,

 

Using Index는 인덱스만으로 원하는 데이터를 추출 하였음을 알 수 있다. 

 

 

  public boolean ThreadRunner(int allCount, int offset) {

        boolean flag= false;

        String endpoint = "http://########.####.###.####";
        String region = "##-######-#";
        String accesskey = "####";
        String secretkey = "####";
        String bucketname = "####";
        AWSCredentials credentials = new BasicAWSCredentials(accesskey, secretkey);

        // Build the Client
        AmazonS3 s3 = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint ,region))
                .withPathStyleAccessEnabled(true)
                .build();

        System.out.println(" target all count : " + allCount);
        log_demo.info(" target all count : " + allCount);

        int limit = 1000;
        // limit 값 1000 고정.
        // aws s3 에서 최대 요청 가능한  object 개수가 1000개이기 때문에.

        try {
            
            log_demo.info("runner! ");
            
            String line;
            
            List<DeleteObjectsRequest.KeyVersion> Arrays = new ArrayList<>();
            DeleteObjectsRequest multiObjectDeleteRequest = new DeleteObjectsRequest(bucketname);

			/* offset 성능으로 인해 쿼리 수정 필요 */
  			List<String> target = jdbcTemplate.queryForList("select s.`path`" +
                    " from bc_media as m" +
                    " join bc_scene as s on m.media_id = s.media_id" +
                    " where m.media_type = 'proxy'" +
                    " limit 1000 OFFSET " + offset, String.class);

		
        	//SUB 쿼리 내부의 모든 항목이 index 컬럼으로 이루어지도록 구성.
            //커버링 인덱스를 쓸 경우 쿼리는 다음과 같음. 
            /* select temp.`path`,temp.`scene_id`, m.media_id , temp.media_id
                 from bc_media as m
                 join 
                 ( select scene_id, media_id 
                    from bc_scene
                    where scene_id < 225221999
                    order by scene_id desc 
                    limit 225221999
                 ) as temp
                on temp.media_id = m.media_id 
                where m.media_type= 'proxy';  */
 
            log_demo.info(" offset : " + offset);
            
            
            for (int i =0; i < target.size(); i ++) {
                String temp = target.get(i);
                log_demo.info(temp);
                Arrays.add(new DeleteObjectsRequest.KeyVersion(temp));
            }

            multiObjectDeleteRequest.setKeys(Arrays);
            long beforeTime = System.currentTimeMillis();

            DeleteObjectsResult delObjRes = s3.deleteObjects(multiObjectDeleteRequest);

           
            long afterTime = System.currentTimeMillis();
            long time_chker = (afterTime - beforeTime);
          
            log_demo.info(" delete required time chk : " + time_chker);
           
        } catch ( Exception r){
        
            r.printStackTrace();
        }
        if (offset > allCount) {

            log_demo.info(" 총 작업량 : " + allCount + " / 종료합니다. ");
        
        } else {
            flag =true;
            log_demo.info(" offset vlaue : " + offset);
        }
        return flag;
    }

 

커버링 인덱스&nbsp; 출처 :&nbsp;https://velog.io/@ddongh1122/MySQL-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0

https://velog.io/@ddongh1122/MySQL-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0

 

[MySQL] 페이징 성능 개선

일반적인 웹 서비스에서 페이징은 매우 흔하게 사용되는 기능이다. 요 근래까지는 페이징 성능 최적화의 필요성을 그다지 느끼지 못하였는데, 최근 5000만 row에 달하는 전체 회원을 대상으로 하

velog.io

 

 

삭제 마지막 포스팅

 

https://girinprogram93.tistory.com/66

 

[AWS S3] 임시테이블을 활용한 1억 4천만건 데이터 삭제 요청

https://girinprogram93.tistory.com/62 커서 방식 페이징으로 변경하기 전에 미리 알아보려 한다. 🥞🥞 오프셋 기반 페이징의 단점 : LIMIT / OFFSET 을 이용할 경우 offset이 늘어나는 양에 따라 비효율적인 " d

girinprogram93.tistory.com

 

320x100
반응형