Rumah  >  Soal Jawab  >  teks badan

Mengapa kemas kini pertanyaan ini gagal dilaksanakan dengan jayanya?

<p>Saya mempunyai 2 meja, pelanggan (3000 baris) dan phone_call_log (350,000 baris). </p> <p>Saya perlu melaksanakan masa panggilan terakhir kepada setiap pelanggan menggunakan log panggilan (lebih pantas untuk carian bahagian hadapan). </p> <p>Indeksnya adalah seperti berikut:</p> <ul> <li>masa_mula (cap masa)</li> <li>panggilan(bigint(32) tidak ditandatangani)</li> <li>Pemanggil(bigint(32) tidak ditandatangani)</li> <li>Nombor telefon (bigint(32) tidak ditandatangani)</li> <li>last_call(timestamp)</li> </ul> <p>Apabila menjalankan pertanyaan ini, untuk lajur pemanggil/pemanggil, masa penyiapan adalah kurang daripada 2 saat tanpa pernyataan OR, tetapi dengan pernyataan OR, ia tidak akan selesai (dalam ujian, saya tidak membiarkannya berjalan selama lebih daripada 30 minit). </p> <pre class="brush:sql;toolbar:false;">KEMASKINI pelanggan SET pelanggan.last_call = ( PILIH maks(phone_call_log.start_time) DARI phone_call_log WHERE phone_call_log.callee = pelanggan.nombor telefon ATAU phone_call_log.caller = pelanggan.nombor telefon ) DI MANA pelanggan.nombor telefon BUKAN NULL DAN panjang(pelanggan.nombor telefon) > DAN pelanggan.nombor telefon > </pra></p>
P粉885562567P粉885562567413 hari yang lalu510

membalas semua(2)saya akan balas

  • P粉009186469

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

    terpantas

    Tukar strim data untuk mengemas kini apabila panggilan masukcustomers.last_call.

    Kemas kini sambungan

    UPDATEJOIN相比,IN ( SELECT ... )Kesannya lebih baik.

    atau

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

    Satu penyelesaian ialah melakukan dua UPDATE, dan gunakan indeks yang sesuai:

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

    Ini memerlukan mencipta indeks berikut pada phone_call_log:

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

    dan padam pemanggil indeks lajur tunggal semasa dan penerima.

    Jenis data

    Untuk nombor telefon, gunakan BIGINT可能是错误的,特别是考虑到LENGTH(customers.phonenumber) > 6.

    Sebenarnya, semuanya berpunca daripada ujian mudah:

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

    Setiap >检查都会检查NOT NULL; gunakan hanya satu daripadanya berdasarkan jenis data, dan indekskannya.

    (Sila berikan SHOW CREATE TABLE; 'Bahasa Inggeris' tidak cukup tepat.)

    balas
    0
  • P粉354602955

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

    Pertanyaan menggunakan OR tidak boleh menggunakan indeks dengan cekap. Saya cadangkan anda mencuba perkara berikut:

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

    Sila ambil perhatian bahawa GREATEST mempunyai masalah mengendalikan nilai NULL.

    balas
    0
  • Batalbalas