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

Petunjuk HINT_PASS_DISTINCT_THROUGH mengurangi jumlah Entitas yang dikembalikan per halaman untuk PageRequest hingga di bawah ukuran halaman yang dikonfigurasi (PostgreSQL)

Masalah yang Anda uji coba berkaitan dengan cara Anda menggunakan HINT_PASS_DISTINCT_THROUGH petunjuk.

Petunjuk ini memungkinkan Anda untuk menunjukkan Hibernate bahwa DISTINCT kata kunci tidak boleh digunakan dalam SELECT pernyataan yang dikeluarkan terhadap database.

Anda memanfaatkan fakta ini untuk memungkinkan kueri Anda diurutkan menurut bidang yang tidak disertakan dalam DISTINCT daftar kolom.

Namun, petunjuk ini seharusnya tidak digunakan.

Petunjuk ini hanya harus digunakan jika Anda yakin tidak akan ada perbedaan antara menerapkan atau tidak menggunakan DISTINCT kata kunci ke SQL SELECT pernyataan, karena SELECT pernyataan sudah akan mengambil semua nilai yang berbeda per se . Idenya adalah meningkatkan kinerja kueri dengan menghindari penggunaan DISTINCT yang tidak perlu pernyataan.

Ini biasanya yang akan terjadi jika Anda menggunakan query.distinct metode dalam kueri kriteria Anda, dan Anda join fetching hubungan anak. Artikel bagus ini dari @VladMihalcea menjelaskan cara kerja petunjuk secara detail.

Di sisi lain, ketika Anda menggunakan paging, itu akan mengatur OFFSET dan LIMIT - atau yang serupa, tergantung pada basis data yang mendasarinya - dalam SQL SELECT pernyataan yang dikeluarkan terhadap database, membatasi jumlah maksimum hasil kueri Anda.

Seperti yang dinyatakan, jika Anda menggunakan HINT_PASS_DISTINCT_THROUGH petunjuk, SELECT pernyataan tidak akan berisi DISTINCT kata kunci dan, karena gabungan Anda, itu berpotensi memberikan catatan duplikat dari entitas utama Anda. Catatan ini akan diproses oleh Hibernate untuk membedakan duplikat, karena Anda menggunakan query.distinct , dan itu sebenarnya akan menghapus duplikat jika diperlukan. Saya rasa inilah alasan mengapa Anda mungkin mendapatkan lebih sedikit catatan daripada yang diminta di Pageable .

Jika Anda menghapus petunjuk, sebagai DISTINCT kata kunci dilewatkan dalam pernyataan SQL yang dikirim ke database, sejauh Anda hanya memproyeksikan informasi entitas utama, itu akan mengambil semua catatan yang ditunjukkan oleh LIMIT dan inilah mengapa ia akan selalu memberi Anda jumlah catatan yang diminta.

Anda dapat mencoba dan fetch join entitas anak Anda (bukan hanya join dengan mereka). Ini akan menghilangkan masalah tidak dapat menggunakan bidang yang perlu Anda urutkan di kolom DISTINCT kata kunci dan, sebagai tambahan, Anda akan dapat menerapkan, sekarang secara sah, petunjuknya.

Tetapi jika Anda melakukannya, itu akan menimbulkan masalah lain bagi Anda:jika Anda menggunakan join fetch dan pagination, untuk mengembalikan entitas utama dan koleksinya, Hibernate tidak akan lagi menerapkan pagination pada tingkat database - ini tidak akan menyertakan OFFSET atau LIMIT kata kunci dalam pernyataan SQL, dan akan mencoba membuat paginasi hasilnya di memori. Ini adalah HHH000104 Hibernate yang terkenal peringatan:

HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!

@VladMihalcea menjelaskannya dengan sangat rinci di bagian terakhir ini artikel.

Dia juga mengusulkan satu solusi yang mungkin untuk masalah Anda, Fungsi Jendela .

Dalam kasus penggunaan Anda, alih-alih menggunakan Specification s, idenya adalah Anda mengimplementasikan DAO Anda sendiri. DAO ini hanya perlu memiliki akses ke EntityManager , yang tidak banyak karena Anda dapat menyuntikkan @PersistenceContext . Anda :

@PersistenceContext
protected EntityManager em;

Setelah Anda memiliki EntityManager ini , Anda dapat membuat kueri asli dan menggunakan fungsi jendela untuk membangun, berdasarkan Pageable . yang disediakan informasi, pernyataan SQL yang tepat yang akan dikeluarkan terhadap database. Ini akan memberi Anda lebih banyak kebebasan tentang bidang apa yang digunakan untuk menyortir atau apa pun yang Anda butuhkan.

Seperti yang ditunjukkan oleh artikel yang dikutip terakhir, Fungsi Jendela adalah fitur yang didukung oleh semua basis data walikota.

Dalam kasus PostgreSQL, Anda dapat dengan mudah menemukannya di dokumentasi resmi .

Akhirnya, satu opsi lagi, sebenarnya disarankan oleh @nickshoe, dan dijelaskan dengan sangat rinci di artikel dia mengutip, adalah melakukan proses penyortiran dan paging dalam dua fase:pada fase pertama, Anda perlu membuat kueri yang akan mereferensikan entitas anak Anda dan di mana Anda akan menerapkan paging dan pengurutan. Kueri ini akan memungkinkan Anda untuk mengidentifikasi id entitas utama yang akan digunakan, pada tahap kedua proses, untuk mendapatkan entitas utama itu sendiri.

Anda dapat memanfaatkan DAO khusus yang disebutkan di atas untuk menyelesaikan proses ini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres:Berbeda tetapi hanya untuk satu kolom

  2. Instalasi / Menjalankan Basis Data Lokal Postgres

  3. PostgreSQL - Tetapkan nilai untuk setiap baris berdasarkan kriteria

  4. Kesalahan Protokol PostgreSQL. Penyiapan sesi gagal.. kesalahan

  5. Bagaimana cara menambahkan Kolom baru di tabel setelah kolom ke-2 atau ke-3 di Tabel menggunakan postgres?