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

Mengoptimalkan GROUP BY + COUNT DISTINCT pada kolom jsonb yang tidak bersarang

Dengan asumsi id tidak hanya UNIQUE - sebagaimana diberlakukan oleh UNIQUE INDEX . Anda - tetapi juga NOT NULL . (Itu tidak ada dalam definisi tabel Anda.)

SELECT meta_split.key, meta_split.value, count(*)
FROM   voc_cc348779bdc84f8aab483f662a798a6a v
CROSS  JOIN LATERAL jsonb_each(v.meta) AS meta_split
GROUP  BY meta_split.key, meta_split.value;

Setara lebih pendek:

SELECT meta_split.key, meta_split.value, count(*)
FROM   voc_cc348779bdc84f8aab483f662a798a6a v, jsonb_each(v.meta) AS meta_split
GROUP  BY 1, 2;

LEFT [OUTER] JOIN adalah kebisingan karena tes berikut WHERE meta_split.value IS NOT NULL memaksa INNER JOIN omong-omong. Menggunakan CROSS JOIN sebagai gantinya.

Juga, karena jsonb tidak mengizinkan kunci duplikat pada level yang sama (artinya id yang sama hanya dapat muncul sekali per (key, value) ), DISTINCT hanya kebisingan mahal. count(v.id) melakukan hal yang sama lebih murah. Dan count(*) setara, dan lebih murah, namun - dengan asumsi id adalah NOT NULL seperti yang dinyatakan di atas.

count(*) memiliki implementasi terpisah dan sedikit lebih cepat dari count(<value>) . Ini agak berbeda dari count(v.*) . Itu menghitung semua baris, apa pun yang terjadi. Sedangkan form lainnya tidak menghitung NULL nilai.

Artinya, selama id tidak boleh NULL - seperti yang dinyatakan di atas. id harus benar-benar PRIMARY KEY , yang diimplementasikan dengan indeks B-tree unik secara internal, dan semua kolom - cukup id di sini - apakah NOT NULL secara implisit. Atau setidaknya NOT NULL . UNIQUE INDEX tidak sepenuhnya memenuhi syarat sebagai pengganti, masih memungkinkan NULL nilai yang tidak dianggap sama dan diperbolehkan beberapa kali. Lihat:

Selain itu, indeks tidak berguna di sini, karena semua baris harus tetap dibaca. Jadi ini tidak akan pernah menjadi sangat murah. Tapi 62 ribu baris bukan jumlah baris yang melumpuhkan dengan cara apa pun - kecuali jika Anda memiliki banyak kunci di jsonb kolom.

Opsi yang tersisa untuk mempercepatnya:

  1. Normalisasikan desain Anda. Menghapus dokumen JSON tidak bebas biaya.

  2. Pertahankan tampilan yang terwujud. Kelayakan dan biaya sangat bergantung pada pola penulisan Anda.

Di situlah indeks dapat berperan lagi ...




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana saya bisa mendapatkan daftar semua fungsi yang disimpan dalam database skema tertentu di PostgreSQL?

  2. Menghapus COMMENT ON dari semua objek di PostgreSQL

  3. Memperbarui kolom integer dari anggota jsonb gagal dengan:kolom bertipe integer tetapi ekspresi bertipe jsonb

  4. Buat daftar dengan hari pertama dan terakhir bulan untuk periode tertentu

  5. Cara Menghapus Trailing Zeros dari Desimal di PostgreSQL