Pourquoi cette mise à jour de requête ne parvient-elle pas à s'exécuter correctement ?
P粉885562567
P粉885562567 2023-09-03 16:39:14
0
2
544
<p>J'ai 2 tables, clients (3 000 lignes) et phone_call_log (350 000 lignes). </p> <p>Je dois implémenter l'heure du dernier appel pour chaque client à l'aide des journaux d'appels (plus rapide pour la recherche frontale). </p> <p>L'index est le suivant :</p> <ul> <li>start_time (horodatage)</li> <li>call(bigint(32) non signé)</li> <li>Appelant(bigint(32) non signé)</li> <li>Numéro de téléphone (bigint(32) non signé)</li> <li>dernier_appel (horodatage)</li> </ul> <p>Lors de l'exécution de cette requête, pour les colonnes appelant/appelé, le temps d'exécution est inférieur à 2 secondes sans l'instruction OR, mais avec l'instruction OR, elle ne se terminera pas (lors des tests, je ne l'ai pas laissé s'exécuter pendant plus de 30 minutes). </p> <pre class="brush:sql;toolbar:false;">MISE À JOUR des clients SET clients.last_call = ( SELECT max(phone_call_log.start_time) DE phone_call_log OÙ phone_call_log.callee = clients.numéro de téléphone OU phone_call_log.caller = clients.numéro de téléphone ) OÙ clients.numéro de téléphone N'EST PAS NULL ET longueur (clients.numéro de téléphone) > 6 ET clients.numéro de téléphone > 1000000 ; </pre></p>
P粉885562567
P粉885562567

répondre à tous(2)
P粉009186469

le plus rapide

Modifiez le flux de données pour le mettre à jour lorsqu'un appel arrivecustomers.last_call.

Mettre à jour la connexion

UPDATEJOIN相比,IN ( SELECT ... )L'effet est meilleur.

ou

OR会降低性能。查询很可能会为每个客户扫描整个phone_call_log.

Une solution consiste à en faire deux UPDATE et à utiliser l'index approprié :

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

Cela nécessite de créer l'index suivant sur phone_call_log :

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

et supprimez l'appelant et l'appelé d'index à colonne unique actuels.

Type de données

Pour les numéros de téléphone, utilisez BIGINT可能是错误的,特别是考虑到LENGTH(customers.phonenumber) > 6.

En fait, tout se résume à un simple test :

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

Chacun >检查都会检查NOT NULL ; utilisez-en un seul en fonction du type de données et indexez-le.

(Veuillez fournir SHOW CREATE TABLE ; « anglais » n'est pas assez précis.)

P粉354602955

Les requêtes utilisant OR ne peuvent pas utiliser l'index efficacement. Je vous suggère d'essayer ce qui suit :

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

Veuillez noter que GREATEST a des problèmes pour gérer les valeurs NULL.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal