Why does this query update fail to execute successfully?
P粉885562567
2023-09-03 16:39:14
<p>I have 2 tables, customers (3000 rows) and phone_call_log (350,000 rows). </p>
<p>I need to implement the time of the last call to each customer using call logs (faster for frontend search). </p>
<p>The index is as follows:</p>
<ul>
<li>start_time (timestamp)</li>
<li>call(bigint(32) unsigned)</li>
<li>Caller(bigint(32) unsigned)</li>
<li>Phone number (bigint(32) unsigned)</li>
<li>last_call(timestamp)</li>
</ul>
<p>When running this query, for the caller/callee columns, the completion time is less than 2 seconds without the OR statement, but with the OR statement, it will not complete (in testing, I did not let it run for more than 30 minutes ). </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>
fastest
When a call comes in, change the data flow to update
customers.last_call
.Update connection
UPDATE
Compared withJOIN
,IN (SELECT ...)
works better.or
OR
will reduce performance. The query will most likely scan the entirephone_call_log
for each customer.One workaround is to do two
UPDATE
, and use the appropriate index:This requires creating the following index on
phone_call_log
:AndDelete the current single column index caller and callee.
type of data
For phone numbers, using
BIGINT
may be wrong, especially consideringLENGTH(customers.phonenumber) > 6
.Actually, all of this boils down to a simple test:
Every
>
check checksNOT NULL
; only one of them is used, depending on the data type, and indexed.(Please provide
SHOW CREATE TABLE
; 'English' is not accurate enough.)Queries using
OR
cannot effectively use the index. I suggest you try the following:Please note that
GREATEST
has issues handling NULL values.