1#!/bin/sh2docker run -d --rm --name postgres -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_DB=postgres -e POSTGRES_PASSWORD=secret -v $(pwd)/data:/var/lib/postgresql/data postgres:11
3docker exec -i postgres bash<<EOF
4sleep 5
5psql -a postgres postgres <<EOF2
6select version();
7create table if not exists item(id numeric(20) primary key, name varchar(100), price numeric(20));
8create table if not exists attr(item_id numeric(20), name varchar(20), value numeric(20), primary key(item_id, name));
9do \\$\\$
10declare
11 cnt numeric(20) := 0;
12begin
13 delete from item;
14 delete from attr;
15 commit;
16 insert into item values (1, '商品1', 100);
17 insert into item values (2, '商品2', 150);
18 commit;
19 for i in 1..15 loop
20 select count(*) into cnt from item;
21 insert into item select id + cnt, concat('商品', cast(id+cnt as varchar(20))), price from item;
22 commit;
23 end loop;
24 insert into attr values(50, '属性1', 300);
25 insert into attr values(100, '属性2', 400);
26 commit;
27 for i in 1..9 loop
28 select max(item_id) into cnt from attr;
29 insert into attr select item_id + cnt, name, value from attr;
30 commit;
31 end loop;
32end \\$\\$;
33vacuum item;
34analyze item;
35vacuum attr;
36analyze attr;
37explain analyze select * from item left join attr on item.id=attr.item_id where item.price=150 and attr.name='属性2';
38explain analyze select * from item left join attr on item.id=attr.item_id where item.price=150 and attr.name='属性3';
39\\q
40EOF241exit42EOF
43docker stop postgres
説明
docker runはpostgres:11イメージからコンテナを作りデーモン起動しています。
docker execは作ったコンテナ上でbashを起動し、EOFまでのhere documentをコンテナ内で実行しています。
docker stopは最後に終了させています。
here documentの中身は、5秒待ってpsqlでpostgresサーバーに繋げてさらに内側のhere documentでSQLを実行してるだけです。
実行しているSQLについては読めば分かるでしょう。
do $$~end $$までは匿名のプロシージャです。
データを水増しする際に変数が必要だったので、仕方なく使っています。
1postgres=# select * from item left join attr on item.id=attr.item_id where item.id in (1,2,3,25,50,75,100,125,150,175,200) order by item.id;2 id | name | price | item_id | name |value3-----+---------+-------+---------+-------+-------41| 商品1|100|||52| 商品2|150|||63| 商品3|100|||725| 商品25|100|||850| 商品50|150|50| 属性1|300975| 商品75|100|||10100| 商品100|150|100| 属性2|40011125| 商品125|100|||12150| 商品150|150|150| 属性1|30013175| 商品175|100|||14200| 商品200|150|200| 属性2|40015(11rows)1617postgres=#
実行結果
bash
1$ sh create_env.sh
2f86d2c5b542fb0a5a862c0aba425c61423c9693296462bfb8d6ca709ed76b766
3select version();4 version
5------------------------------------------------------------------------------------------------------------------------------------
6 PostgreSQL 11.16(Debian 11.16-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1)6.3.0 20170516, 64-bit
7(1 row)89create table if not exists item(id numeric(20) primary key, name varchar(100), price numeric(20));10CREATE TABLE
11create table if not exists attr(item_id numeric(20), name varchar(20), value numeric(20), primary key(item_id, name));12CREATE TABLE
13do$$14declare15 cnt numeric(20) :=0;16begin
17 delete from item;18 delete from attr;19 commit;20 insert into item values (1, '商品1', 100);21 insert into item values (2, '商品2', 150);22 commit;23foriin1..15 loop
24select count(*) into cnt from item;25 insert into item selectid + cnt, concat('商品', cast(id+cnt as varchar(20))), price from item;26 commit;27 end loop;28 insert into attr values(50, '属性1', 300);29 insert into attr values(100, '属性2', 400);30 commit;31foriin1..9 loop
32select max(item_id) into cnt from attr;33 insert into attr select item_id + cnt, name, value from attr;34 commit;35 end loop;36end $$;37DO
38vacuum item;39VACUUM
40analyze item;41ANALYZE
42vacuum attr;43VACUUM
44analyze attr;45ANALYZE
46explain analyze select * from item left join attr on item.id=attr.item_id where item.price=150 and attr.name='属性2';47 QUERY PLAN
48-----------------------------------------------------------------------------------------------------------------
49 Hash Join (cost=26.20..1349.37rows=256width=41)(actual time=0.251..14.552rows=512loops=1)50 Hash Cond: (item.id = attr.item_id)51 -> Seq Scan on item (cost=0.00..1237.20rows=32751width=22)(actual time=0.009..10.173rows=32768loops=1)52 Filter: (price ='150'::numeric)53 Rows Removed by Filter: 3276854 -> Hash (cost=19.80..19.80rows=512width=19)(actual time=0.173..0.174rows=512loops=1)55 Buckets: 1024 Batches: 1 Memory Usage: 34kB
56 -> Seq Scan on attr (cost=0.00..19.80rows=512width=19)(actual time=0.006..0.113rows=512loops=1)57 Filter: ((name)::text ='属性2'::text)58 Rows Removed by Filter: 51259 Planning Time: 0.269 ms
60 Execution Time: 14.607 ms
61(12 rows)6263explain analyze select * from item left join attr on item.id=attr.item_id where item.price=150 and attr.name='属性3';64 QUERY PLAN
65------------------------------------------------------------------------------------------------------
66 Nested Loop (cost=0.29..28.11rows=1width=41)(actual time=0.086..0.087rows=0loops=1)67 -> Seq Scan on attr (cost=0.00..19.80rows=1width=19)(actual time=0.086..0.086rows=0loops=1)68 Filter: ((name)::text ='属性3'::text)69 Rows Removed by Filter: 102470 -> Index Scan using item_pkey on item (cost=0.29..8.31rows=1width=22)(never executed)71 Index Cond: (id = attr.item_id)72 Filter: (price ='150'::numeric)73 Planning Time: 0.287 ms
74 Execution Time: 0.106 ms
75(9 rows)7677\q
78postgres