AWS RDS MySQL chậm dần theo thời gian

Aug 24 2020

Tôi đã đọc nhiều bài viết về chủ đề này nhưng không có bài nào nói về AWS RDS MySQL Database. Kể từ ba ngày trước, tôi đang chạy tập lệnh python trong phiên bản AWS EC2 ghi các hàng trong cơ sở dữ liệu AWS RDS MySQL của tôi. Tôi phải viết 35 triệu hàng, vì vậy tôi biết điều này sẽ mất một thời gian. Định kỳ, tôi kiểm tra hiệu suất của cơ sở dữ liệu và ba ngày sau (hôm nay) tôi nhận thấy rằng cơ sở dữ liệu đang chậm lại. Khi bắt đầu, 100.000 hàng đầu tiên được viết chỉ trong 7 phút (đây là ví dụ về các hàng tôi đang làm việc)

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

Sau ba ngày, 5.385.662 hàng đã được viết trong cơ sở dữ liệu, nhưng bây giờ phải mất gần 3 giờ để viết 100.000 hàng. Điều gì đang xảy ra?

Phiên bản EC2 mà tôi đang chạy là t2.small. Ở đây bạn có thể kiểm tra thông số kỹ thuật nếu bạn cần như vậy: EC2 SPECS . Cơ sở dữ liệu RDS mà tôi đang chạy là db.t2.small. Kiểm tra thông số kỹ thuật tại đây: RDS SPECS

Tôi sẽ đính kèm ở đây một số biểu đồ về hiệu suất của cơ sở dữ liệu và Phiên bản EC2: Db CPU / Db Bộ nhớ / Db Ghi IOPS / Db Ghi thông lượng / Mạng EC2 vào (byte) / Mạng EC2 ra (byte)

Sẽ rất tuyệt nếu bạn có thể giúp tôi. Cảm ơn rất nhiều.

CHỈNH SỬA 1: Làm cách nào để chèn hàng? Như tôi đã nói trước đây, tôi có một tập lệnh python chạy trên một phiên bản EC2, tập lệnh này đọc các tệp văn bản, thực hiện một số tính toán với các giá trị này và sau đó ghi mọi hàng "mới" vào cơ sở dữ liệu. Đây là một đoạn mã nhỏ của tôi. Làm cách nào để đọc các tệp văn bản?

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()

Tôi biết không có gì except:để can thiệp vào các trytuyên bố, nhưng đây chỉ là một phần của kịch bản. Tôi nghĩ phần quan trọng là cách tôi chèn mọi hàng. Trong trường hợp tôi không cần tính toán với các giá trị, tôi sẽ sử dụng Load Data Infileđể ghi các tệp văn bản vào cơ sở dữ liệu. Tôi chỉ nhận ra rằng có lẽ không phải là một ý kiến ​​hay cho commitmỗi lần tôi chèn một hàng. Tôi sẽ cố gắng cam kết sau 10.000 hàng hoặc lâu hơn.

Trả lời

11 MLu Aug 24 2020 at 06:03

Các phiên bản T2 và T3 (bao gồm cả các phiên bản db.t2 db.t3) sử dụng hệ thống Tín dụng CPU . Khi phiên bản không hoạt động, nó sẽ tích lũy Tín dụng CPU mà sau đó nó có thể sử dụng để chạy nhanh hơn trong khoảng thời gian ngắn - Hiệu suất bùng nổ . Một khi bạn cạn kiệt các khoản tín dụng, nó sẽ chậm lại so với hiệu suất Cơ bản .

Một tùy chọn là bật cài đặt T2 / T3 Unlimited trong cấu hình RDS của bạn, điều này sẽ cho phép phiên bản chạy ở tốc độ tối đa trong thời gian cần thiết, nhưng bạn sẽ phải trả thêm các khoản tín dụng cần thiết.

Tùy chọn khác là thay đổi loại phiên bản thành db.m5 hoặc một số loại không phải T2 / T3 khác hỗ trợ hiệu suất nhất quán.

Dưới đây là giải thích chuyên sâu hơn về các khoản tín dụng CPU và cách chúng được tích lũy và chi tiêu: Về việc làm rõ điều kiện làm việc t2 và t3?

Hy vọng rằng sẽ giúp :)

9 RickJames Aug 24 2020 at 07:09
  • Hàng đơn INSERTschậm gấp 10 lần so với hàng 100 INSERTshoặc LOAD DATA.

  • UUID chậm, đặc biệt khi bảng trở nên lớn.

  • UNIQUEchỉ mục cần được kiểm tra trước khi kết thúc một iNSERT.

  • Không phải duy nhất INDEXescó thể được thực hiện trong nền, nhưng chúng vẫn chịu một số tải.

Vui lòng cung cấp SHOW CREATE TABLEvà phương pháp được sử dụng cho INSERTing. Có thể có nhiều mẹo hơn.

7 tater Aug 23 2020 at 23:07

Mỗi khi bạn cam kết (các) chỉ số giao dịch cần được cập nhật. Độ phức tạp của việc cập nhật chỉ mục có liên quan đến số lượng hàng trong bảng, vì vậy khi số lượng hàng tăng lên, cập nhật chỉ mục sẽ dần dần chậm hơn.

Giả sử bạn đang sử dụng bảng InnoDB, bạn có thể làm như sau:

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

Sau đó, thực hiện chèn, nhưng hàng loạt chúng để một câu lệnh chèn (ví dụ) vài chục hàng. Thích INSERT INTO table_name VALUES ((<row1 data>), (<row2 data>), ...). Khi quá trình chèn hoàn tất,

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

Bạn có thể điều chỉnh điều này cho tình huống của riêng mình, ví dụ: nếu số lượng hàng lớn thì có thể bạn muốn chèn nửa triệu sau đó cam kết. Điều này giả định rằng cơ sở dữ liệu của bạn không 'sống' (tức là người dùng chủ động đọc / ghi vào nó) trong khi bạn thực hiện việc chèn, vì bạn đang tắt các kiểm tra mà bạn có thể dựa vào khi họ nhập dữ liệu.