我已经阅读了很多关于这个主题的帖子,但没有一篇是关于 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 SPECS 。我正在运行的 RDS 数据库是 db.t2.small。在此处查看规格:RDS SPECS
我将在此处附上一些关于数据库和 EC2 实例性能的图表: Db CPU / Db Memory / Db Write IOPS / Db Write Throughput / EC2 Network in (bytes) / EC2 Network out (bytes)
如果你能帮助我,那就太好了。非常感谢。
编辑 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 行左右之后提交。
T2 和 T3 实例(包括 db.t2 db.t3 实例)使用CPU Credit系统。当实例空闲时,它会累积 CPU 积分,然后它可以使用这些积分在短时间内更快地运行 -突增性能。一旦你耗尽积分,它就会减慢到基线性能。
一种选择是在您的 RDS 配置中启用T2/T3 Unlimited设置,这将使实例在需要时全速运行,但您需要为所需的额外积分付费。
另一种选择是将实例类型更改为 db.m5 或其他支持一致性能的非 T2/T3 类型。
以下是对 CPU 积分及其累积和使用方式的更深入解释:关于澄清 t2 和 t3 工作条件?
希望有帮助:)
单排比
INSERTs
100 排慢 10 倍INSERTs
或LOAD DATA
.UUID 很慢,尤其是当表变大时。
UNIQUE
索引需要在完成之前iNSERT
检查。非唯一
INDEXes
可以在后台完成,但它们仍然需要一些负载。请提供
SHOW CREATE TABLE
和使用的方法INSERTing
。可能还有更多提示。每次提交事务索引时都需要更新。更新索引的复杂度与表中的行数有关,因此随着行数的增加,索引更新会逐渐变慢。
假设您正在使用 InnoDB 表,您可以执行以下操作:
然后进行插入,但对它们进行批处理,以便一个语句插入(例如)几十行。喜欢
INSERT INTO table_name VALUES ((<row1 data>), (<row2 data>), ...)
。插入完成后,您可以根据自己的情况进行调整,例如,如果行数很大,那么您可能想要插入一百万然后提交。这假设您的数据库在您进行插入时不是“活动的”(即用户主动读取/写入它),因为您正在禁用检查,否则当他们输入数据时您可能会依赖这些检查。