MySQL LOAD DATA INFILE 使用帮助
我想加载一个看起来像这样的CSV文件:
Acct. No.,1-15 Days,16-30 Days,31-60 Days,61-90 Days,91-120 Days,Beyond 120 Days
2314134101,898.89,8372.16,5584.23,7744.41,9846.54,2896.25
2414134128,5457.61,7488.26,9594.02,6234.78,273.7,2356.13
2513918869,2059.59,7578.59,9395.51,7159.15,5827.48,3041.62
1687950783,4846.85,8364.22,9892.55,7213.45,8815.33,7603.4
2764856043,5250.11,9946.49,8042.03,6058.64,9194.78,8296.2
2865446086,596.22,7670.04,8564.08,3263.85,9662.46,7027.22
,4725.99,1336.24,9356.03,1572.81,4942.11,6088.94
,8248.47,956.81,8713.06,2589.14,5316.68,1543.67
,538.22,1473.91,3292.09,6843.89,2687.07,9808.05
,9885.85,2730.72,6876,8024.47,1196.87,1655.29
但是你会发现,有些字段是不完整的。我在想,如果第一列缺失,MySQL会不会就跳过这一行。当我运行这个命令时:
LOAD DATA LOCAL INFILE 'test-long.csv' REPLACE INTO TABLE accounts
FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(cf_535, cf_580, cf_568, cf_569, cf_571, cf_572);
MySQL的输出是:
Query OK, 41898 rows affected, 20948 warnings (0.78 sec)
Records: 20949 Deleted: 20949 Skipped: 0 Warnings: 20948
虽然行数只有20,949,但MySQL却报告说影响了41,898行。这是为什么呢?而且,表格里的内容其实并没有什么变化。我也看不到生成的警告到底是什么。我想使用LOAD DATA INFILE,因为用Python更新每一行需要半秒钟,这样对于一个有20,000多条记录的文件来说,就要花2.77个小时。
更新:我修改了代码,把自动提交设置为'False',并添加了一个db.commit()语句:
# Tell MySQLdb to turn off auto-commit
db.autocommit(False)
# Set count to 1
count = 1
while count < len(contents):
if contents[count][0] != '':
cursor.execute("""
UPDATE accounts SET cf_580 = %s, cf_568 = %s, cf_569 = %s, cf_571 = %s, cf_572 = %s
WHERE cf_535 = %s""" % (contents[count][1], contents[count][2], contents[count][3], contents[count][4], contents[count][5], contents[count][0]))
count += 1
try:
db.commit()
except:
db.rollback()
2 个回答
0
如果你在加载数据时使用了REPLACE这个关键词,那么“Deleted: ”后面的数字就表示实际被替换掉的行数。
2
你这里基本上有三个问题,按相反的顺序来看:
- 你在用Python插入数据时,是不是每条语句都单独执行?你可能需要把这些操作放在一个事务中,也就是用“开始事务”和“提交”来包裹起来。要是你每次都提交一次,插入2万条数据可能要花上几个小时。
- 你的导入语句定义了6个字段,但CSV文件里有7个字段。这就解释了为什么数据库里的行数是双倍的:每一行输入都会在数据库中生成两行,第二行的字段2到6都是空的。
- 不完整的行会被插入时,缺失的列会用空值或默认值填充。这可能不是你想要的,特别是对于那些格式不正确的行。
如果你的Python程序即使在一个事务中也运行得不够快,至少应该让程序在导入之前先处理和清理数据文件。如果账户号码是主键,这样看起来是合理的,那么插入空值的行要么会导致整个导入失败,要么如果开启了自动编号,就会导致导入一些错误的数据。