-
-
Save horgh/f3e8ede81d866844e7d162d677968bf0 to your computer and use it in GitHub Desktop.
PostgreSQL sub-query LIMIT behaviour
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nested Loop (cost=2.10..14.80 rows=1 width=21) (actual time=0.082..0.780 rows=5 loops=1) | |
Join Filter: (t3.t2_id = t2.t2_id) | |
Rows Removed by Join Filter: 30 | |
-> Seq Scan on t2 (cost=0.00..1.01 rows=1 width=10) (actual time=0.006..0.019 rows=11 loops=1) | |
Filter: ((t2_val)::text ~~ 'he%'::text) | |
-> Nested Loop (cost=2.10..13.73 rows=5 width=15) (actual time=0.017..0.063 rows=3 loops=11) | |
-> Limit (cost=1.33..2.25 rows=5 width=7) (actual time=0.010..0.023 rows=4 loops=11) | |
InitPlan 1 (returns $0) | |
-> Aggregate (cost=1.32..1.33 rows=1 width=8) (actual time=0.050..0.051 rows=1 loops=1) | |
-> Seq Scan on t1 t1_1 (cost=0.00..1.26 rows=26 width=0) (actual time=0.002..0.024 rows=26 loops=1) | |
-> Seq Scan on t1 (cost=0.00..1.65 rows=9 width=7) (actual time=0.008..0.015 rows=4 loops=11) | |
Filter: ((t1_id IS NOT NULL) AND (t1_id < 100) AND ((t1_val)::text ~~ 'h%'::text) AND (random() <= ('5'::double precision / ($0)::double precision))) | |
Rows Removed by Filter: 17 | |
-> Bitmap Heap Scan on t3 (cost=0.76..2.28 rows=1 width=8) (actual time=0.004..0.004 rows=1 loops=49) | |
Recheck Cond: (t1_id = t1.t1_id) | |
Heap Blocks: exact=35 | |
-> Bitmap Index Scan on t3_pkey (cost=0.00..0.76 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=49) | |
Index Cond: (t1_id = t1.t1_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BEGIN; | |
DROP TABLE IF EXISTS t1; | |
DROP TABLE IF EXISTS t2; | |
DROP TABLE IF EXISTS t3; | |
create table t1 ( | |
t1_id int, | |
t1_val varchar, | |
PRIMARY KEY (t1_id) | |
); | |
create table t2 ( | |
t2_id int, | |
t2_val varchar | |
); | |
create table t3 ( | |
t1_id int, | |
t2_id int, | |
PRIMARY KEY (t1_id) | |
); | |
INSERT INTO t1 VALUES(0, 'hi'); | |
INSERT INTO t1 VALUES(1, 'hi'); | |
INSERT INTO t1 VALUES(2, 'hi'); | |
INSERT INTO t1 VALUES(3, 'hi'); | |
INSERT INTO t1 VALUES(4, 'hi'); | |
INSERT INTO t1 VALUES(5, 'hi'); | |
INSERT INTO t1 VALUES(6, 'hi'); | |
INSERT INTO t1 VALUES(7, 'hi'); | |
INSERT INTO t1 VALUES(8, 'hi'); | |
INSERT INTO t1 VALUES(9, 'hi'); | |
INSERT INTO t1 VALUES(10, 'hi'); | |
INSERT INTO t1 VALUES(11, 'hi'); | |
INSERT INTO t1 VALUES(12, 'hi'); | |
INSERT INTO t1 VALUES(13, 'hi'); | |
INSERT INTO t1 VALUES(14, 'hi'); | |
INSERT INTO t1 VALUES(15, 'hi'); | |
INSERT INTO t1 VALUES(16, 'hi'); | |
INSERT INTO t1 VALUES(17, 'hi'); | |
INSERT INTO t1 VALUES(18, 'hi'); | |
INSERT INTO t1 VALUES(19, 'hi'); | |
INSERT INTO t1 VALUES(20, 'hi'); | |
INSERT INTO t1 VALUES(21, 'hi'); | |
INSERT INTO t1 VALUES(22, 'hi'); | |
INSERT INTO t1 VALUES(23, 'hi'); | |
INSERT INTO t1 VALUES(24, 'hi'); | |
INSERT INTO t1 VALUES(25, 'hi'); | |
ANALYZE t1; | |
INSERT INTO t2 VALUES(0, 'hello'); | |
ANALYZE t2; | |
INSERT INTO t2 VALUES(1, 'hello'); | |
INSERT INTO t2 VALUES(2, 'hello'); | |
INSERT INTO t2 VALUES(3, 'hello'); | |
INSERT INTO t2 VALUES(4, 'hello'); | |
INSERT INTO t2 VALUES(5, 'hello'); | |
INSERT INTO t2 VALUES(6, 'hello'); | |
INSERT INTO t2 VALUES(7, 'hello'); | |
INSERT INTO t2 VALUES(8, 'hello'); | |
INSERT INTO t2 VALUES(9, 'hello'); | |
INSERT INTO t2 VALUES(10, 'hello'); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(0, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(1, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(2, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(3, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(4, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(5, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(6, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(7, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(8, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(9, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(10, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(11, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(12, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(13, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(14, 0); | |
INSERT INTO t3 (t1_id, t2_id) VALUES(15, 1); | |
EXPLAIN ANALYZE | |
SELECT * FROM | |
(SELECT * FROM t1 | |
WHERE t1_id IS NOT NULL AND | |
t1_id < 100 AND | |
t1_val LIKE 'h%' AND | |
random() <= (5::double precision)/(SELECT COUNT(*) FROM t1) | |
LIMIT 5 | |
) AS t1 | |
JOIN t3 ON t3.t1_id = t1.t1_id | |
JOIN t2 USING (t2_id) | |
WHERE t2.t2_val LIKE 'he%'; | |
COMMIT; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use warnings; | |
use DBI (); | |
sub main { | |
if (@ARGV != 4) { | |
print { \*STDERR } "Usage: $0 <host> <database> <username> <password>\n"; | |
return 0; | |
} | |
my ($host, $database, $user, $pass) = @ARGV; | |
my $dsn = "dbi:Pg:database=$database;host=$host"; | |
my $dbh = DBI->connect($dsn, $user, $pass); | |
die "error connecting to database" unless $dbh; | |
my $sql = q{ | |
SELECT * FROM | |
(SELECT * FROM t1 | |
WHERE t1_id IS NOT NULL AND | |
t1_id < 100 AND | |
t1_val LIKE 'h%' AND | |
random() <= (5::double precision)/(SELECT COUNT(*) FROM t1) | |
LIMIT 5 | |
) AS t1 | |
JOIN t3 ON t3.t1_id = t1.t1_id | |
JOIN t2 USING (t2_id) | |
WHERE t2.t2_val LIKE 'he%' | |
}; | |
while (1) { | |
my $rows = $dbh->selectall_arrayref($sql); | |
my $n = scalar @{ $rows }; | |
if ($n <= 5) { | |
next; | |
} | |
print "received $n rows\n"; | |
last; | |
} | |
return 1; | |
} | |
main() ? 0 : 1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment