MySQL更新表列基于来自其他两个表的值

时间:2015-10-15 12:32:13

标签: mysql for-loop memory sql-update

我有三张桌子: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不为null,则使用EmailCore中的商店

2)否则使用来自Guest的商店

我知道,对于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)构建的大表,并且我一直在耗尽内存或者进程在完成之前锁定并且我必须反弹数据库集群。如果我将行限制在0.5密耳左右,我可以使查询工作。但是,JournalEntry包含大约20万条记录。

任何人都可以想到更好/更快的内存密集型方式来完成这项任务吗?也许是一个for循环/程序。欢迎任何建议。

1 个答案:

答案 0 :(得分:0)

您的性能问题可能是因为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;