我有几个包含以下字段的大表:
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
| fid1 | varchar(10) | NO | MUL | NULL | |
| fid2 | varchar(10) | NO | | NULL | |
| cnt | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
我在{fid1,fid2,cnt}
上有索引,每个表的行数超过20000000
。
我希望将这些表合并为一个,如果fid1
和fid2
都匹配,那么新的cnt
值将是cnt
的总和在这些表中。
我尝试了merge and add values from two tables中建议的方式,并获得类似
的内容SELECT COALESCE(A.fid1, B.fid1) AS fid1, COALESCE(A.fid2, B.fid2) AS fid2, (COALESCE(A.cnt,0)+COALESCE(B.cnt,0))
FROM test1 A LEFT JOIN test2 B ON a.fid1 = b.fid1 AND A.fid2 = B.fid2
UNION
SELECT COALESCE(A.fid1, B.fid1) AS fid1, COALESCE(A.fid2, B.fid2) AS fid2, (COALESCE(A.cnt,0)+COALESCE(B.cnt,0))
FROM test1 A RIGHT JOIN test2 B ON a.fid1 = b.fid1 AND A.fid2 = B.fid2
但是,由于我有几个表并且它们都非常大,因此使用UNION
的此方法非常耗时。有没有其他方法可以有效地实施它或以任何方式优化它?
谢谢!
答案 0 :(得分:1)
无法在多个表上加速UNION,因为UNION只是一个连接,在您的用例中,您必须读取所有表中的所有行。因此,如果您有20个表,并从每个表中选择,那将不会比一个联合更快(给定相同的过滤器)
如果您想要合并数百万行,则所需的时间取决于select-s和写入,并且写入总是较慢,因此:
使用一些脚本或代码生成一个长查询的连接:
INSERT INTO new_table
SELECT fid1,fid2, sum(cnt) as cnt FROM
(
SELECT fid1, fid2, cnt FROM table1
UNION ALL
SELECT fid1, fid2, cnt FROM table2
UNION ALL
SELECT fid1, fid2, cnt FROM table3
UNION ALL
SELECT fid1, fid2, cnt FROM table4
UNION ALL
SELECT fid1, fid2, cnt FROM table5
UNION ALL
SELECT fid1, fid2, cnt FROM table6
) GROUP BY fid1, fid2;
如果你的缓冲区用完了,你可能会考虑不一次做所有事情,而是将table1,2,3,4,5,6,7,8,9,10总结为sum1,表11,12,13 ,14,15,16,17,18,19,20为sum2,并在末尾求和。这意味着更多的工作,更多的分配存储空间,以及更多的磁盘io,但峰值缓冲区的使用率更低。
最后:您可以添加(或启用)您需要的密钥。
提示:
更新:修正了用户seahawk所指出的UNION ALL