AWS RDS MySQL 随着时间的推移而变慢

AWS RDS MySQL 随着时间的推移而变慢

我读过很多关于这个主题的帖子,但没有一篇谈论 AWS RDS MySQL 数据库。三天前,我在 AWS EC2 实例中运行一个 Python 脚本,该脚本向我的 AWS RDS MySQL 数据库中写入行。我必须写入 3500 万行,所以我知道这需要一些时间。我定期检查数据库的性能,三天后(今天)我意识到数据库的速度正在变慢。启动时,前 100,000 行仅用了 7 分钟就写入了(这是我正在处理的行的一个示例)

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

三天后,数据库中已写入 5,385,662 行,但现在写入 100,000 行需要近 3 个小时。发生了什么?

我正在运行的 EC2 实例是 t2.small。如果需要,您可以在这里查看规格:EC2 规格 。我运行的 RDS 数据库是 db.t2.small。在此处查看规格:RDS 规格

我将在这里附上一些有关数据库和 EC2 实例性能的图表: 数据库 CPU/数据库内存/数据库写入 IOPS/数据库写入吞吐量/ 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或慢10倍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;

您可以根据自己的情况进行调整,例如,如果行数很大,那么您可能希望插入五十万行然后提交。这假设您在执行插入操作时数据库不是“实时”的(即用户主动读取/写入数据库),因为您禁用了您在输入数据时可能依赖的检查。

相关内容