Why does this query update fail to execute successfully?
P粉885562567
P粉885562567 2023-09-03 16:39:14
0
2
548
<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>
P粉885562567
P粉885562567

reply all(2)
P粉009186469

fastest

When a call comes in, change the data flow to update customers.last_call.

Update connection

UPDATECompared with JOIN, IN (SELECT ...) works better.

or

OR will reduce performance. The query will most likely scan the entire phone_call_log for each customer.

One workaround is to do two UPDATE, and use the appropriate index:

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 ...

This requires creating the following index on phone_call_log:

INDEX(callee, start_time)
    INDEX(caller, start_time)

AndDelete the current single column index caller and callee.

type of data

For phone numbers, using BIGINT may be wrong, especially considering LENGTH(customers.phonenumber) > 6.

Actually, all of this boils down to a simple test:

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

Every > check checks NOT NULL; only one of them is used, depending on the data type, and indexed.

(Please provide SHOW CREATE TABLE; 'English' is not accurate enough.)

P粉354602955

Queries using OR cannot effectively use the index. I suggest you try the following:

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)
)

Please note that GREATEST has issues handling NULL values.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template