為什麼這個查詢更新無法成功執行?
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值時有問題。