我有三张表:Guest、JournalEntry和EmailCore,其中有以下相关列

JournalEntry (je)
------------------------------
id | guestId | emailId | store


EmailCore (ec)
----------
id | store


Guest (g)
----------
id | store

具有以下关系:
je.guestId -> g.id

je.emailId -> ec.id

我刚刚在JournalEntry表中添加了store列,其中包含:
ALTER TABLE `JournalEntry` ADD `store` int(11) NOT NULL;

我正尝试使用以下规则将所有存储数据从EmailCore和Guest迁移到JournalEntry中:
1)如果je.emailId不为空,则使用来自EmailCore的存储
2)其他客人使用商店
我知道一个事实,JournalEntry的每一行都会在EmailCore或Guest中有一个商店。
考虑到这一点,我尝试了以下问题:
-- Migrate the proper store number to the store column of JournalEntry
-- If present, EmailCore.store has priority
UPDATE JournalEntry je
LEFT JOIN Guest g on g.id = je.guestId
LEFT JOIN EmailCore ec on ec.id = je.emailId
SET je.store = COALESCE(ec.store, g.store);

这个查询的问题是,它试图构建一个从所有三个表(je、ec&g)构建的大表,而在它完成之前,我的内存一直不足,或者进程被锁定,我不得不重新启动db集群。如果将行数限制在大约0.5 mil,我就可以让查询正常工作。然而,JournalEntry包含大约2000万条记录。
有谁能想出一种更好/更快、内存占用更少的方法来完成这项任务吗?可能是一个for循环/过程。欢迎提出任何建议。

最佳答案

性能问题可能是因为guestemail_core中有多个匹配行。但是,如果重复项不多,那么索引将有助于查询:

create index idx_guest_id_store on guest(id, store);
create index idx_emailcore_id_store on emailcore(id, store);

但是,如果id已经是主键,那就差不多了。
如果由于连接而获得大量重复行,我将首先建议两个更新:
UPDATE JournalEntry je JOIN
       EmailCore ec
     on ec.id = je.emailId
    SET je.store = ec.store;

UPDATE JournalEntry je JOIN
       Guest g
       on g.id = je.guestId
    SET je.store = g.store;
WHERE je.emailid IS NULL;

然后我将使用子查询简化这些操作:
UPDATE JournalEntry je
    SET je.store = (SELECT ec.store
                    FROM EmailCore ec
                    WHERE ec.id = je.emailId
                    LIMIT 1
                   );

UPDATE JournalEntry je
    SET je.store = (SELECT g.store
                    FROM Guest g
                    WHERE g.id = je.guestId
                    LIMIT 1
                   )
    WHERE je.emailid IS NULL;

10-07 15:39