PostgresQL ekvivalent för found_rows()

Tråden skapades och har fått 7 svar. Det senaste inlägget skrevs .
1

Finns det någon motsvarighet till mySQL's found_rows() som returnerar det antal rader som ens föregående sql-query skulle haft utan limit?

Vad jag alltså vill göra är att helt sonika fråga pgsql "hur många rader fanns det i förra resultatet om jag inte hade haft en limit på 10?"...

Både ja och nej. Nej i det avseendet att det inte finns någon för ändamålet avsedd ickestandard-utökning till SQL-specifikationen som i MySQL, men ja i det avseendet att nästan ingenting är omöjligt med PostgreSQL. Det blir lite bökigare bara, men det går t.ex. att göra med PL/pgSQL-funktioner.

Men annars så skulle jag nog faktiskt köra SELECT-satsen utan LIMIT för att sedan bara hämta ett urval av raderna - på så sätt behöver du bara köra satsen en gång, du får reda på antalet rader utan LIMIT och du kan ändå begränsa antalet rader. Om jag minns rätt är det i princip funktionsmässigt ekvivalent med att köra en LIMIT-sats, så att prestanda blir likvärdiga. Så här kan man t.ex. göra i php:

$resultat = pg_query("SELECT * FROM min_tabell");
$antal_rader = pg_num_rows($resultat);
for($i=10; $i < 20; $i++) {
    $data[] = pg_fetch_row($resultat, $i);
}

Jag antar att det inte påverkar prestandan något? Data skickas inte från servern förräns den hämtas, eller?

Hmmm, här krävs några seriösa EXPLAIN ANALYZE

Ursprungligen av scooterbabe:

Jag antar att det inte påverkar prestandan något? Data skickas inte från servern förräns den hämtas, eller?

Om jag minns specarna för PostgreSQL-protokollet rätt så skickar databashanteraren bara över de rader ur resultatmängden som klienten ber om att få, och om det stämmer ger det i stort sett ingen overhead jämfört med att begränsa med LIMIT. En bonus är att man kan göra ungefär samma sak med MySQL också, och det kan vara bra om du vill ha bakåtkompatibilitet med 3.x. FOUND_ROWS fungerar ju bara i version 4.0 och upp, och före 4.1 var funktionen lite för buggig för att vara 100% tillförlitlig.

Citat:

Hmmm, här krävs några seriösa EXPLAIN ANALYZE

EXPLAIN är ett klart underskattat kommando som fler borde använda sig av. För den nyfikne kan jag också rekommendera en titt på tabellerna pg_class och pg_statistics, åtminstone om man vill veta mer om hur ens SQL-satser optimeras (och varför man ska använda VACUUM ANALYZE).

Jo, visst är det så. Fast när resultatet blir så här http://tosti.dk/victor/cepe.html tar man sig bara för pannan och undrar vad tusan man gjort

Ursprungligen av scooterbabe:

Jo, visst är det så. Fast när resultatet blir så här http://tosti.dk/victor/cepe.html tar man sig bara för pannan och undrar vad tusan man gjort

Wow. Det var en imponerande lista med join-kriterier måste jag då säga.

Om SQL-satsen inte körs särskilt ofta kan det faktiskt vara OK att behålla den som den är. När allt kommer omkring är det ju bara bråkdelar av en sekund det rör sig om, och om satsen bara körs ett par gånger i timmen är det inget problem egentligen. Det krävs *betydligt* mer än så för att få Postgres att gå på knäna. Annars borde du kunna minska tidsåtgången genom att skapa fler index. T.ex. kör du många joins med jämförelser mot kolumnerna "relid" och "id", och där tror jag att du kan vinna mycket tid på att använda index. Se i så fall till att köra vacuum analyze tillräckligt ofta, om du nu inte kör PG 7.4 och använder autovacuum.

Jodå, relid ligger det index på, åtminstone. Men en annan sak har slagit mig vad gäller found_rows(); i många funktioner brukar jag fetcha resultatet (säg de 10 jag limitat fram) med pg_fetch_all() istället för att loopa och fetcha dem med pg_fetch_assoc(), vilket jag har fått för mig är snabbare.

Men om jag nu ska migrera till att hämta samtliga rader och endast itera över de som har intresse kan det ju (väl?) inte vara någon bra idé att köra med pg_fetch_all(), eftersom det innebär att en jättevektor kommer att returneras. Och pg_fetch_all() är ju en funktion som jag bara älskar...

Så frågan är lite vad göra?

* found_rows()-ekvivalent verkar inte finnas, så det är bara att glömma
* limit funkar ju istället, och är det sätt som jag måste köra med om jag vill använda pg_fetch_all()
* eller så kan jag hämta allt och antingen itera över relevanta rader och lägga till dem till min returvektor och returnera en vektor med längden [antal i limit] i första dimensionen, eller hämta _allt_ till en vektor med pg_fetch_all(), för att sedan returnera denna. Kanske snabbare än iteration så länge man håller sig under ett visst antal, men med ett par tio tusen rader i databasen kanske det kan bli lite svårhanterat för php...

Kanske är det bäst att hämta alla rader, och sedan itera över de rader som är relevanta och som man vill returnera. Detta har 2 st fördelar: eftersom funktionen xx_fetch_all() inte finns för mysql, håller man sin pg-php-lösning portningsbar mot mysql, och eftersom inte found_rows() ingår i SQL-syntaxen, blandar man inte in otrevliga, ostandardiserade funktioner i sin kod... hmmm...

Well well, feed back och kommentarer är välkommet... Även om jag antar att det mest blir du, Samuel, som svarar - vi verkar vara de enda postgressarna här....

Ursprungligen av scooterbabe:

* eller så kan jag hämta allt och antingen itera över relevanta rader och lägga till dem till min returvektor och returnera en vektor med längden [antal i limit] i första dimensionen, eller hämta _allt_ till en vektor med pg_fetch_all(), för att sedan returnera denna. Kanske snabbare än iteration så länge man håller sig under ett visst antal, men med ett par tio tusen rader i databasen kanske det kan bli lite svårhanterat för php...

Kanske är det bäst att hämta alla rader, och sedan itera över de rader som är relevanta och som man vill returnera. Detta har 2 st fördelar: eftersom funktionen xx_fetch_all() inte finns för mysql, håller man sin pg-php-lösning portningsbar mot mysql, och eftersom inte found_rows() ingår i SQL-syntaxen, blandar man inte in otrevliga, ostandardiserade funktioner i sin kod... hmmm...

Det borde ju kunna fungera det också, men det kan ju vara en bra idé att laborera lite först och se vilka prestanda du får (du kan ju t.ex. testa att medelst lämpligt skript slänga in några tusen poster i en testdatabas och testa mot). Eftersom Postgres förhoppningsvis redan filtrerat bort rätt mycket i SQL-urvalet borde php-skriptet inte behöva tugga sig igenom alltför mycket. Tänk bara på att php generellt har usla prestanda för stora datamängder, och eftersom funktionerna returnerar kopior kan det vara klokt att inte skicka runt *hela* resultatmängden överallt. Alternativt går det ju att skicka referenser i stället, så slipper man onödig duplicering.

Citat:

Well well, feed back och kommentarer är välkommet... Även om jag antar att det mest blir du, Samuel, som svarar - vi verkar vara de enda postgressarna här....

Bättre det än ingen alls iaf

1
Bevaka tråden