为什么这个查询更新无法成功执行?
P粉885562567
2023-09-03 16:39:14
<p>我有2个表,customers(3000行)和phone_call_log(350,000行)。</p>
<p>我需要使用通话记录(对于前端搜索更快)将最后一次通话的时间实现到每个客户。</p>
<p>索引如下:</p>
<ul>
<li>start_time(时间戳)</li>
<li>调用(bigint(32)无符号)</li>
<li>调用者(bigint(32) 无符号)</li>
<li>电话号码(bigint(32) 无符号)</li>
<li>last_call(时间戳)</li>
</ul>
<p>运行此查询时,没有OR语句的情况下,对于caller / callee列,完成时间小于2秒,但是有了OR语句,将无法完成(在测试中,我没有让它运行超过30分钟)。</p>
<pre class="brush:sql;toolbar:false;">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;
</pre></p>
最快
当有电话呼入时,改变数据流以更新
customers.last_call
。更新连接
UPDATE
与JOIN
相比,IN ( SELECT ... )
效果更好。或者
OR
会降低性能。查询很可能会为每个客户扫描整个phone_call_log
。一种解决方法是进行两个
UPDATE
,并使用适当的索引:这需要在
phone_call_log
上创建以下索引:并且删除当前的单列索引caller和callee。
数据类型
对于电话号码来说,使用
BIGINT
可能是错误的,特别是考虑到LENGTH(customers.phonenumber) > 6
。实际上,所有这些都可以归结为一个简单的测试:
每个
>
检查都会检查NOT NULL
;根据数据类型只使用其中一个,并对其进行索引。(请提供
SHOW CREATE TABLE
;'英文'不够准确。)使用
OR
的查询无法有效地使用索引。我建议你尝试以下方法:请注意,
GREATEST
在处理NULL值时存在问题。