Maison  >  Questions et réponses  >  le corps du texte

Pourquoi cette mise à jour de requête ne parvient-elle pas à s’exécuter correctement ?

<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粉885562567P粉885562567413 Il y a quelques jours504

répondre à tous(2)je répondrai

  • P粉009186469

    P粉0091864692023-09-04 14:58:45

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

    répondre
    0
  • P粉354602955

    P粉3546029552023-09-04 10:38:38

    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.

    répondre
    0
  • Annulerrépondre