AWS RDS MySQL 시간이 지남에 따라 속도가 느려짐

AWS RDS MySQL 시간이 지남에 따라 속도가 느려짐

이 주제에 대한 많은 게시물을 읽었지만 그 중 AWS RDS MySQL 데이터베이스에 관한 게시물은 없습니다. 3일 전부터 AWS RDS MySQL 데이터베이스에 행을 쓰는 AWS EC2 인스턴스에서 Python 스크립트를 실행하고 있습니다. 3,500만 행을 작성해야 하므로 시간이 좀 걸릴 것이라는 것을 알고 있습니다. 주기적으로 데이터베이스 성능을 확인했는데, 3일 후(오늘) 데이터베이스 속도가 느려지고 있다는 사실을 깨달았습니다. 시작했을 때 처음 100,000개의 행이 단 7분 만에 작성되었습니다(이것은 제가 작업 중인 행의 예입니다).

0000002178-14-000056    AccountsPayableCurrent  us-gaap/2014        20131231    0   USD 266099000.0000

3일 후에는 5,385,662개의 행이 데이터베이스에 기록되었지만 지금은 100,000개의 행을 작성하는 데 거의 3시간이 걸립니다. 무슨 일이 일어나고 있나요?

제가 실행 중인 EC2 인스턴스는 t2.small입니다. 필요한 경우 여기에서 사양을 확인할 수 있습니다.EC2 사양 . 제가 실행 중인 RDS 데이터베이스는 db.t2.small입니다. 여기에서 사양을 확인하세요.RDS 사양

여기에 데이터베이스와 EC2 인스턴스의 성능에 대한 몇 가지 차트를 첨부하겠습니다. DB CPU/DB 메모리/DB 쓰기 IOPS/DB 쓰기 처리량/ EC2 네트워크 입력(바이트)/EC2 네트워크 출력(바이트)

당신이 나를 도울 수 있다면 좋을 것입니다. 정말 감사합니다.

편집 1: 행을 어떻게 삽입하나요? 이전에 말했듯이 저는 EC2 인스턴스에서 실행되는 Python 스크립트를 가지고 있습니다. 이 스크립트는 텍스트 파일을 읽고 이러한 값으로 일부 계산을 수행한 다음 모든 "새" 행을 데이터베이스에 씁니다. 여기 내 코드의 작은 부분이 있습니다. 텍스트 파일을 어떻게 읽나요?

for i in path_list:
  notify("Uploading: " + i)
  num_path = "path/" + i + "/file.txt"
  sub_path = "path/" + i + "/file.txt"

  try:
    sub_dict = {}
    with open(sub_path) as sub_file:
      for line in sub_file:
        line = line.strip().split("\t")
        sub_dict[line[0]] = line[1] # Save cik for every accession number
        sub_dict[line[1] + "-report"] = line[25] # Save report type for every CIK
        sub_dict[line[1] + "-frecuency"] = line[28] # Save frecuency for every CIK

    with open(num_path) as num_file:
      for line in num_file:
        num_row = line.strip().split("\t")

        # Reminder: sometimes in the very old reports, cik and accession number does not match. For this reason I have to write 
        # the following statement. To save the real cik.

        try: 
          cik = sub_dict[num_row[0]]
        except:
          cik = num_row[0][0:10]

        try: # If there is no value, pass
          value = num_row[7]
          values_dict = {
                  'cik': cik, 
                  'accession': num_row[0][10::].replace("-", ""),  
                  'tag': num_row[1], 
                  'value': value, 
                  'valueid': num_row[6], 
                  'date': num_row[4]
                  }

          sql = ("INSERT INTO table name (id, tag, value_num, value_id, endtime, cik, report, period) "
              "VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')".format(
                  values_dict['cik'] + values_dict['accession'] + values_dict['date'] + values_dict['value'].split(".")[0] + "-" + values_dict['tag'], 
                  values_dict['tag'], 
                  float(values_dict['value']), 
                  values_dict['valueid'], 
                  values_dict['date'], 
                  int(values_dict['cik']), 
                  sub_dict[values_dict['cik'] + "-report"], 
                  sub_dict[values_dict['cik'] + "-frecuency"]
                  ))

          cursor.execute(sql)
          connection.commit()

except:나는 진술을 캐낼 필요 가 없다는 것을 알고 있지만 try이것은 단지 대본의 일부일뿐입니다. 중요한 부분은 모든 행을 어떻게 삽입하는지라고 생각합니다. 값을 사용하여 계산할 필요가 없는 경우 Load Data Infile텍스트 파일을 데이터베이스에 쓰는 데 사용하겠습니다. 나는 commit행을 삽입할 때마다 좋은 생각이 아닐 수도 있다는 것을 알고 있습니다 . 10,000행 정도 후에 커밋을 시도하겠습니다.

답변1

T2 및 T3 인스턴스(db.t2 db.t3 인스턴스 포함) 사용CPU 크레딧체계. 인스턴스가 유휴 상태이면 짧은 시간 동안 더 빠르게 실행하는 데 사용할 수 있는 CPU 크레딧이 축적됩니다.버스트 성능. 크레딧이 소진되면 속도가 느려집니다.기준 성능.

한 가지 옵션은 활성화하는 것입니다.T2/T3 무제한RDS 구성에서 인스턴스를 필요한 기간 동안 최대 속도로 실행할 수 있도록 설정하지만 필요한 추가 크레딧에 대한 비용을 지불하게 됩니다.

다른 옵션은 인스턴스 유형을 db.m5 또는 일관된 성능을 지원하는 다른 비 T2/T3 유형으로 변경하는 것입니다.

여기에 더 자세한 내용이 있습니다.CPU 크레딧에 대한 설명그리고 적립 및 지출 방법은 다음과 같습니다.t2 및 t3 근무 조건을 명확히 하시겠습니까?

도움이 되었기를 바랍니다 :)

답변2

  • 단일 행 INSERTs은 100행 INSERTs또는 LOAD DATA.

  • UUID는 특히 테이블이 커질 때 느립니다.

  • UNIQUE인덱스를 확인해야합니다~ 전에.iNSERT

  • 고유하지 않은 작업은 INDEXes백그라운드에서 수행할 수 있지만 여전히 약간의 부하가 걸립니다.

SHOW CREATE TABLE에 사용된 방법과 방법을 알려주십시오 INSERTing. 더 많은 팁이 있을 수 있습니다.

답변3

트랜잭션을 커밋할 때마다 인덱스를 업데이트해야 합니다. 인덱스 업데이트의 복잡성은 테이블의 행 수와 관련되어 있으므로 행 수가 증가하면 인덱스 업데이트 속도가 점점 느려집니다.

InnoDB 테이블을 사용한다고 가정하면 다음을 수행할 수 있습니다.

SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET AUTOCOMMIT = 0;
ALTER TABLE table_name DISABLE KEYS;

그런 다음 삽입을 수행하되 하나의 명령문이 수십 개의 행을 삽입하도록 일괄 처리합니다. 좋다 INSERT INTO table_name VALUES ((<row1 data>), (<row2 data>), ...). 삽입이 완료되면,

ALTER TABLE table_name ENABLE KEYS;
SET UNIQUE_CHECKS = 1;
SET FOREIGN_KEY_CHECKS = 1;
COMMIT;

자신의 상황에 맞게 이를 조정할 수 있습니다. 예를 들어 행 수가 큰 경우 50만 개를 삽입한 다음 커밋할 수 있습니다. 이는 삽입을 수행하는 동안 데이터베이스가 '실시간'(즉, 사용자가 적극적으로 읽고 쓰는 중)이 아니라고 가정합니다. 왜냐하면 데이터베이스가 데이터를 입력할 때 의존할 수 있는 검사를 비활성화하고 있기 때문입니다.

관련 정보