Skip to content

Instantly share code, notes, and snippets.

@horgh
Last active January 11, 2018 21:01
Show Gist options
  • Save horgh/f3e8ede81d866844e7d162d677968bf0 to your computer and use it in GitHub Desktop.
Save horgh/f3e8ede81d866844e7d162d677968bf0 to your computer and use it in GitHub Desktop.
PostgreSQL sub-query LIMIT behaviour
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)
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;
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