AWS RDS MySQL wird mit der Zeit langsamer

AWS RDS MySQL wird mit der Zeit langsamer

Ich habe viele Beiträge zu diesem Thema gelesen, aber keiner davon spricht über die AWS RDS MySQL-Datenbank. Seit drei Tagen führe ich ein Python-Skript in einer AWS EC2-Instanz aus, das Zeilen in meine AWS RDS MySQL-Datenbank schreibt. Ich muss 35 Millionen Zeilen schreiben, also weiß ich, dass das einige Zeit dauern wird. In regelmäßigen Abständen überprüfe ich die Leistung der Datenbank und drei Tage später (heute) stelle ich fest, dass die Datenbank langsamer wird. Als sie gestartet wurde, wurden die ersten 100.000 Zeilen in nur 7 Minuten geschrieben (dies ist ein Beispiel für die Zeilen, mit denen ich arbeite).

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

Nach drei Tagen wurden 5.385.662 Zeilen in die Datenbank geschrieben, aber jetzt dauert es fast 3 Stunden, um 100.000 Zeilen zu schreiben. Was ist los?

Die EC2-Instanz, die ich betreibe, ist die t2.small. Hier können Sie bei Bedarf die Spezifikationen überprüfen:EC2-SPEZIFIKATIONEN . Die RDS-Datenbank, die ich verwende, ist db.t2.small. Überprüfen Sie die Spezifikationen hier:RDS-SPEZIFIKATIONEN

Ich füge hier einige Diagramme zur Leistung der Datenbank und der EC2-Instanz an: DB-CPU/DB-Speicher/Datenbank-Schreib-IOPS/Datenbank-Schreibdurchsatz/ EC2-Netzwerk in (Bytes)/EC2-Netzwerkausgang (Bytes)

Es wäre toll, wenn Sie mir helfen könnten. Vielen Dank.

BEARBEITEN 1: Wie füge ich Zeilen ein? Wie ich bereits sagte, läuft auf einer EC2-Instanz ein Python-Skript, das Textdateien liest, einige Berechnungen mit diesen Werten durchführt und dann jede „neue“ Zeile in die Datenbank schreibt. Hier ist ein kleiner Teil meines Codes. Wie lese ich die Textdateien?

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

Ich weiß, dass es keine Möglichkeit gibt, except:die Anweisungen zu kapitulieren try, aber das ist nur ein Teil des Skripts. Ich denke, der wichtige Teil ist, wie ich jede Zeile einfüge. Falls ich keine Berechnungen mit den Werten durchführen muss, schreibe ich Load Data Infiledie Textdateien in die Datenbank. Mir ist nur klar, dass es vielleicht keine gute Idee ist, commitjedes Mal eine Zeile einzufügen. Ich werde versuchen, nach etwa 10.000 Zeilen ein Commit durchzuführen.

Antwort1

T2- und T3-Instanzen (inkl. db.t2 db.t3-Instanzen) verwendenCPU-GuthabenSystem. Wenn die Instanz im Leerlauf ist, sammelt sie CPU-Credits, die sie dann verwenden kann, um für kurze Zeit schneller zu laufen -Burst-Leistung. Sobald Sie die Credits aufgebraucht haben, verlangsamt es sich zu einemBasisleistung.

Eine Möglichkeit besteht darin,T2/T3 UnbegrenztEinstellung in Ihrer RDS-Konfiguration, die die Instanz so lange wie nötig mit voller Geschwindigkeit laufen lässt, Sie zahlen jedoch für die zusätzlich benötigten Credits.

Die andere Möglichkeit besteht darin, den Instanztyp in db.m5 oder einen anderen Nicht-T2/T3-Typ zu ändern, der eine konsistente Leistung unterstützt.

Hier ist eine ausführlichereErklärung der CPU-Creditsund wie sie anfallen und ausgegeben werden:Zur Klärung der Arbeitsbedingungen T2 und T3?

Hoffentlich hilft das :)

Antwort2

  • Einreihige INSERTssind 10-mal so langsam wie 100-reihige INSERTsoder LOAD DATA.

  • UUIDs sind langsam, insbesondere wenn die Tabelle groß wird.

  • UNIQUEIndizes müssen überprüft werdenVorBeenden eines iNSERT.

  • Nicht eindeutige Vorgänge INDEXeskönnen im Hintergrund ausgeführt werden, verursachen aber dennoch eine gewisse Belastung.

Bitte geben Sie SHOW CREATE TABLEdie verwendete Methode an INSERTing. Möglicherweise gibt es noch weitere Tipps.

Antwort3

Bei jedem Commit einer Transaktion müssen die Indizes aktualisiert werden. Die Komplexität der Indexaktualisierung hängt von der Anzahl der Zeilen in der Tabelle ab. Mit zunehmender Zeilenanzahl wird die Indexaktualisierung also zunehmend langsamer.

Vorausgesetzt, Sie verwenden InnoDB-Tabellen, können Sie Folgendes tun:

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

Führen Sie dann die Einfügungen durch, aber stapelweise, so dass eine Anweisung (z. B.) mehrere Dutzend Zeilen einfügt. Wie INSERT INTO table_name VALUES ((<row1 data>), (<row2 data>), ...). Wenn die Einfügungen abgeschlossen sind,

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

Sie können dies an Ihre eigene Situation anpassen. Wenn beispielsweise die Anzahl der Zeilen sehr groß ist, möchten Sie vielleicht eine halbe Million einfügen und dann einen Commit ausführen. Dies setzt voraus, dass Ihre Datenbank nicht „live“ ist (d. h. Benutzer lesen/schreiben aktiv), während Sie die Einfügungen durchführen, da Sie Prüfungen deaktivieren, auf die Sie sich sonst bei der Dateneingabe verlassen könnten.

verwandte Informationen