Rumah >pangkalan data >tutorial mysql >Bagaimanakah Saya Boleh Mengoptimumkan GROUP BY Queries untuk Mendapatkan Baris Terkini dengan Cekap untuk Setiap Pengguna?

Bagaimanakah Saya Boleh Mengoptimumkan GROUP BY Queries untuk Mendapatkan Baris Terkini dengan Cekap untuk Setiap Pengguna?

DDD
DDDasal
2025-01-24 00:37:14276semak imbas

How Can I Optimize GROUP BY Queries to Efficiently Retrieve the Latest Row for Each User?

Strategi Pengoptimuman untuk GROUP BY Query untuk Mendapatkan Baris Terkini bagi setiap Pengguna

Diberikan jadual dengan mesej pengguna yang distrukturkan sebagai log_date, user_id dan muatan , tugasnya adalah untuk mendapatkan semula rekod terkini untuk setiap pengguna dengan cekap sebelum sesuatu yang khusus tarikh.

Indeks Berbilang Ruang

Untuk meningkatkan prestasi bacaan, cipta indeks berbilang lajur pada user_id dan log_date:

CREATE INDEX log_combo_idx ON log (user_id, log_date DESC NULLS LAST);

Indeks- Hanya Imbasan dengan Indeks Penutup

Untuk indeks sahaja imbasan, tentukan indeks penutup yang merangkumi lajur muatan:

CREATE INDEX log_combo_covering_idx ON log (user_id, log_date DESC NULLS LAST) INCLUDE (payload);

SELECT DISTINCT ON()

Untuk jadual kecil atau beberapa baris setiap user_id, menggunakan SELECT DISTINCT ON() boleh menjadi cekap:

SELECT DISTINCT ON(user_id) log_date, payload
FROM log
WHERE log_date <= :mydate
ORDER BY user_id, log_date DESC;

Imbasan Langkau Indeks Emulasi

Untuk jadual besar dengan banyak baris setiap user_id, pertimbangkan untuk meniru imbasan langkau indeks menggunakan CTE rekursif dengan sambung LATERAL:

WITH RECURSIVE cte AS (
   (
   SELECT user_id, log_date, payload
   FROM   log
   WHERE  log_date <= :mydate
   ORDER  BY user_id, log_date DESC NULLS LAST
   LIMIT  1
   )
   UNION ALL
   SELECT l.*
   FROM   cte c
   CROSS  JOIN LATERAL (
      SELECT l.user_id, l.log_date, l.payload
      FROM   log l
      WHERE  l.user_id > c.user_id  -- lateral reference
      AND    log_date <= :mydate    -- repeat condition
      ORDER  BY l.user_id, l.log_date DESC NULLS LAST
      LIMIT  1
      ) l
   )
TABLE  cte
ORDER  BY user_id;

Jadual Pengguna Asingkan

Jika jadual pengguna yang berasingan wujud, penyelesaian yang dipermudahkan mungkin:

LATERAL Sertai

SELECT u.user_id, l.log_date, l.payload
FROM   users u
CROSS  JOIN LATERAL (
   SELECT l.log_date, l.payload
   FROM   log l
   WHERE  l.user_id = u.user_id         -- lateral reference
   AND    l.log_date <= :mydate
   ORDER  BY l.log_date DESC NULLS LAST
   LIMIT  1
   ) l;

Subkueri Berkaitan

SELECT user_id, (combo1).*              -- note parentheses
FROM (
   SELECT u.user_id
        , (SELECT (l.log_date, l.payload)::combo
           FROM   log l
           WHERE  l.user_id = u.user_id
           AND    l.log_date <= :mydate
           ORDER  BY l.log_date DESC NULLS LAST
           LIMIT  1) AS combo1
   FROM   users u
   ) sub;

Pengoptimuman ini meningkatkan prestasi pertanyaan dengan menggunakan indeks , meniru imbasan langkau dan memanfaatkan jadual berasingan untuk maklumat pengguna.

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mengoptimumkan GROUP BY Queries untuk Mendapatkan Baris Terkini dengan Cekap untuk Setiap Pengguna?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn