sql >> Databasteknik >  >> RDS >> PostgreSQL

Tips HINT_PASS_DISTINCT_THROUGH minskar antalet enheter som returneras per sida för en PageRequest till under den konfigurerade sidstorleken (PostgreSQL)

Problemet du experimenterar har att göra med hur du använder HINT_PASS_DISTINCT_THROUGH ledtråd.

Detta tips låter dig indikera Hibernate att DISTINCT nyckelord ska inte användas i SELECT uttalande utfärdat mot databasen.

Du utnyttjar detta faktum för att tillåta att dina frågor sorteras efter ett fält som inte ingår i DISTINCT kolumnlista.

Men det är inte så det här tipset ska användas.

Denna ledtråd måste endast användas när du är säker på att det inte kommer att vara någon skillnad mellan att tillämpa eller inte använda en DISTINCT nyckelord till SQL SELECT sats, eftersom SELECT uttalandet kommer redan att hämta alla distinkta värden i och för sig . Tanken är att förbättra prestandan för frågan och undvika användningen av en onödig DISTINCT uttalande.

Detta är vanligtvis vad som händer när du använder query.distinct metod i dina kriteriefrågor, och du join fetching barnrelationer. Denna fantastiska artikel av @VladMihalcea förklara hur tipset fungerar i detalj.

Å andra sidan, när du använder personsökning kommer den att ställa in OFFSET och LIMIT - eller något liknande, beroende på den underliggande databasen - i SQL SELECT uttalande som utfärdats mot databasen, vilket begränsar din fråga till ett maximalt antal resultat.

Som sagt, om du använder HINT_PASS_DISTINCT_THROUGH ledtråd, SELECT satsen kommer inte att innehålla DISTINCT sökord och, på grund av dina kopplingar, kan det potentiellt ge dubbletter av din huvudenhet. Dessa poster kommer att bearbetas av Hibernate för att skilja dubbletter, eftersom du använder query.distinct , och det kommer faktiskt att ta bort dubbletter om det behövs. Jag tror att detta är anledningen till att du kan få färre poster än vad som begärts i din Pageable .

Om du tar bort tipset, som DISTINCT nyckelordet skickas i SQL-satsen som skickas till databasen, så långt du bara projicerar information om huvudenheten, kommer det att hämta alla poster som anges med LIMIT och det är därför du alltid får det begärda antalet poster.

Du kan försöka fetch join dina underordnade enheter (istället för att bara join). med dem). Det kommer att eliminera problemet med att inte kunna använda fältet du behöver sortera efter i kolumnerna i DISTINCT nyckelord och dessutom kommer du att kunna tillämpa, nu på ett legitimt sätt, tipset.

Men om du gör det kommer du att få ett annat problem:om du använder join-hämtning och paginering, för att returnera huvudenheterna och dess samlingar, kommer Hibernate inte längre att tillämpa paginering på databasnivå - det kommer inte att inkludera OFFSET eller LIMIT nyckelord i SQL-satsen, och den kommer att försöka paginera resultaten i minnet. Detta är den berömda Hibernate HHH000104 varning:

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

@VladMihalcea förklara det mycket detaljerat i den sista delen av detta artikel.

Han föreslog också en möjlig lösning på ditt problem, Fönsterfunktioner .

I ditt använda fall istället för att använda Specification s, tanken är att du implementerar din egen DAO. Denna DAO behöver bara ha tillgång till EntityManager , vilket inte är så mycket eftersom du kan injicera din @PersistenceContext :

@PersistenceContext
protected EntityManager em;

När du har den här EntityManager , kan du skapa inbyggda frågor och använda fönsterfunktioner för att bygga, baserat på den tillhandahållna Pageable information, rätt SQL-sats som kommer att utfärdas mot databasen. Detta kommer att ge dig mycket mer frihet om vilka fält som används för sortering eller vad du behöver.

Som den senast citerade artikeln indikerar är Window Functions en funktion som stöds av alla borgmästardatabaser.

När det gäller PostgreSQL kan du enkelt hitta dem i den officiella dokumentationen .

Slutligen, ytterligare ett alternativ, faktiskt föreslagit av @nickshoe, och förklarat i detalj i artikel han citerade, är att utföra sorterings- och personsökningsprocessen i två faser:i den första fasen måste du skapa en fråga som refererar till dina underordnade enheter och där du kommer att tillämpa personsökning och sortering. Den här frågan låter dig identifiera ID:n för huvudenheterna som kommer att användas, i den andra fasen av processen, för att erhålla själva huvudenheterna.

Du kan dra nytta av den tidigare nämnda anpassade DAO för att utföra denna process.



  1. hur man formaterar datum som kommer från MYSQL

  2. Det gick inte att ladda den begärda klassen:com.mysql.jdbc.Driver på JBoss med hjälp av HIbernate

  3. Få inlägg från alla kategorier utom en kategori

  4. Codeigniter och oracle odefinierad konstant:OCI_COMMIT_ON_SUCCESS