PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Optimalkan kueri maksimum berdasarkan grup

Dengan asumsi relatif sedikit baris dalam options untuk banyak baris dalam records .

Biasanya, Anda akan melihat tabel options yang dirujuk dari records.option_id , idealnya dengan batasan kunci asing. Jika tidak, saya sarankan untuk membuatnya untuk menegakkan integritas referensial:

CREATE TABLE options (
  option_id int  PRIMARY KEY
, option    text UNIQUE NOT NULL
);

INSERT INTO options
SELECT DISTINCT option_id, 'option' || option_id -- dummy option names
FROM   records;

Maka tidak perlu lagi meniru pemindaian indeks longgar dan ini menjadi sangat sederhana dan cepat . Subkueri terkait dapat menggunakan indeks biasa pada (option_id, id) .

SELECT option_id, (SELECT max(id)
                   FROM   records
                   WHERE  option_id = o.option_id) AS max_id
FROM   options o
ORDER  BY 1;

Ini termasuk opsi tanpa kecocokan di tabel records . Anda mendapatkan NULL untuk max_id dan Anda dapat dengan mudah menghapus baris seperti itu di SELECT outer luar jika diperlukan.

Atau (hasil yang sama):

SELECT option_id, (SELECT id
                   FROM   records
                   WHERE  option_id = o.option_id
                   ORDER  BY id DESC NULLS LAST
                   LIMIT  1) AS max_id
FROM   options o
ORDER  BY 1;

Mungkin sedikit lebih cepat. Subquery menggunakan urutan pengurutan DESC NULLS LAST - sama dengan fungsi agregat max() yang mengabaikan nilai NULL. Hanya menyortir DESC akan memiliki NULL terlebih dahulu:

  • Mengapa nilai NULL didahulukan saat memesan DESC dalam kueri PostgreSQL?

Indeks sempurna untuk ini:

CREATE INDEX on records (option_id, id DESC NULLS LAST);

Urutan pengurutan indeks tidak terlalu menjadi masalah saat kolom ditentukan NOT NULL .

Masih ada pemindaian berurutan di tabel kecil options , itu hanya cara tercepat untuk mengambil semua baris. ORDER BY dapat membawa pemindaian indeks (hanya) untuk mengambil baris yang telah diurutkan sebelumnya.
Tabel besar records hanya diakses melalui pemindaian indeks (bitmap) atau, jika memungkinkan, pemindaian hanya indeks .

db<>main biola di sini - menampilkan dua pemindaian indeks saja untuk kasus sederhana
sqlfiddle lama

Atau gunakan LATERAL bergabung untuk efek serupa di Postgres 9.3+:

  • Optimalkan kueri GROUP BY untuk mengambil baris terbaru per pengguna


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah mungkin membuat kueri SQL rekursif?

  2. Penerapan dan Pemeliharaan PostgreSQL dengan Ansible

  3. Bagaimana Tan() Bekerja di PostgreSQL

  4. Skema Buat PostgreSQL

  5. Setara dengan HEX() dan UNHEX() MySQL di Postgres?