为什么这个更新查询没有完成?

Why does this update query not complete?

我有 2 个表,customers(3000 行)和 phone_call_log(350 000 行)。

我需要使用通话记录具体化每个客户的最后一次通话时间(前端搜索速度更快)

索引在:

运行 对于调用者/被调用者列,没有 OR 语句的查询在 < 2 秒内完成,但是在 OR 就位的情况下,它不会完成(我不允许它 运行 测试时间超过 30 分钟)。

UPDATE customers
SET customers.last_call = (
     SELECT max(phone_call_log.start_time)
     FROM phone_call_log
     WHERE phone_call_log.callee = customers.phonenumber
        OR phone_call_log.caller = customers.phonenumber
)
WHERE customers.phonenumber IS NOT NULL
  AND length(customers.phonenumber) > 6
  AND customers.phonenumber > 1000000;

使用 OR 的查询无法使用索引(效率不高)。我建议您尝试以下操作:

UPDATE customers
SET last_call = GREATEST(
    (SELECT MAX(start_time) FROM phone_call_log WHERE callee = customers.phonenumber),
    (SELECT MAX(start_time) FROM phone_call_log WHERE caller = customers.phonenumber)
)

请注意 GREATEST 存在 NULL 值问题。

最快

更改数据流以在有来电时更新customers.last_call

更新加入

UPDATE 使用 JOIN 比使用 IN ( SELECT ... )

效果更好

OR 是性能杀手。该查询可能会针对每个客户扫描整个 phone_call_log

一个解决方法是做两个 UPDATEs 并有合适的索引:

UPDATE 
    SET customers.last_call = GREATEST( customers.last_call,
                 ( select max(phone_call_log.start_time)
                      FROM  phone_call_log
                     WHERE  phone_call_log.callee = customers.phonenumber 
                 )
    WHERE ...
UPDATE 
    SET customers.last_call = GREATEST( customers.last_call,
                 ( ... caller ... )
                 )
    WHERE ...

phone_call_log:

上需要这些索引
    INDEX(callee, start_time)
    INDEX(caller, start_time)

删除调用者和被调用者当前的 1 列索引。

数据类型

BIGINT 用于 phone 数字可能是错误的并且适得其反,特别是考虑到 LENGTH(customers.phonenumber) > 6.

事实上,所有这些都归结为一个测试:

where customers.phonenumber is not null
  AND LENGTH(customers.phonenumber) > 6
  AND customers.phonenumber > 1000000;

无论如何,每个 > 检查 NOT NULL;根据数据类型,仅使用其中一个。并将其编入索引。

(请提供 SHOW CREATE TABLE;'English' 不太准确。)