【发布时间】:2021-03-29 16:58:45
【问题描述】:
在我的应用程序中,我允许使用 CSV 文件更新用户数据,最大限制为 100K 行。
csv 文件中的每一行都包含c_id,a_id, country_code
用户上传一个 CSV 文件,然后我从该文件创建一个查询
到目前为止一切正常
问题是我的表变大了,现在包含 69,123,914 行(我上次检查时)
现在执行时间大约需要 5 分钟
在这种情况下,最佳做法是什么?
这是表结构
| Feild | Type | null | Key | Default | extra |
|---|---|---|---|---|---|
| c_id | bigint(20) | NO | PRI | null | |
| a_id | int(11) | NO | PRI | null | |
| country_code | varchar(2) | NO | PRI | null | |
| last_update | timestamp | NO | "" | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| created_time | timestamp | NO | "" | CURRENT_TIMESTAMP | |
| is_deleted | tinyint(1) | NO | "" | 0 |
这是从 CSV 行生成的查询
UPDATE my_table
SET is_deleted = 1
WHERE is_deleted = 0
AND (
(c_id = '1' AND country_code = 'TH' AND a_id = '-1')
OR (c_id = '1' AND country_code = 'RO' AND a_id = '-1')
OR (c_id = '1' AND country_code = 'PT' AND a_id = '-1')
OR (c_id = '2' AND country_code = 'JM' AND a_id = '-1')
OR (c_id = '35' AND country_code = 'AM' AND a_id = '-1')
OR (c_id = '77' AND country_code = 'BA' AND a_id = '-1')
OR (c_id = '77' AND country_code = 'MD' AND a_id = '-1')
OR (c_id = '77' AND country_code = 'LT' AND a_id = '-1')
OR (c_id = '123' AND country_code = 'TT' AND a_id = '-1')
OR (..... until 100k) `
这是执行计划
| Operation | Params | rows | raw des |
|---|---|---|---|
| INDEX_SCAN (range) | table: my_table; index: PRIMARY; | 100,000 | Using where |
【问题讨论】:
-
我会将 CSV 加载到一个表中,然后加入该表,而不是动态创建一个巨大的 WHERE 子句。
-
问题在于数据库执行时间,而不是查询构建
-
如果您不想使用中间表,那么只需将您的动态查询至少转换为
UPDATE my_table SET is_deleted = 1 WHERE is_deleted = 0 and (c_id, country_code, a_id) IN ((8338731, 'TH', -1), (8338731, 'RO', -1), ...)。(c_id, country_code, a_id)索引的存在将会改善。 -
或(.....直到 100k - 这是否意味着每个 c_id = 8338731 ?只有 100k 中的一部分会被更新?
-
附言。我认为删除
WHERE is_deleted = 0不会降低性能 - MySQL 只更新实际更改的值,而不是全部更改。
标签: mysql sql optimization