Skip to content

Commit c9e8311

Browse files
committed
Update documentation
1 parent fa17b17 commit c9e8311

File tree

2 files changed

+121
-8
lines changed

2 files changed

+121
-8
lines changed

tpch2.sql

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ group by
159159
n_name
160160
order by
161161
revenue desc;
162-
-- Time: 30911.679 ms (00:30.912)
162+
-- Seq: Time: 30186.833 ms (00:30.187)
163+
-- Par: Time: 15492.048 ms (00:15.492)
164+
163165

164166

165167

@@ -197,10 +199,6 @@ create foreign table supplier_fdw (
197199
s_acctbal float4 not null
198200
) server vops_server options (table_name 'vsupplier');
199201

200-
set enable_material=false;
201-
set enable_mergejoin=false;
202-
203-
204202
select
205203
n_name,
206204
count(*),
@@ -220,10 +218,8 @@ group by
220218
n_name
221219
order by
222220
revenue desc;
223-
-- Time: 55101.292 ms (00:55.101)
224-
221+
-- Time: 41108.297 ms (00:41.108)
225222

226-
\echo Foreign data wrapper result
227223

228224
create table hlineitem(
229225
l_suppkey int4 not null,

vops.html

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ <h1>Vectorized Operations (VOPS)</h1>
1616
<li><a href="#indexes">Using indexes</a></li>
1717
<li><a href="#populating">Preparing data for VOPS</a></li>
1818
<li><a href="#unnest">Back to normal tuples</a></li>
19+
<li><a href="#fdw">Back to normal tables</a></li>
1920
</ul>
2021
<li><a href="#transform">Standard SQL query transformation</a></li>
2122
<li><a href="#example">Example</a></li>
@@ -571,6 +572,122 @@ <h3><a name="unnest">Back to normal tuples</a></h3>
571572
</pre>
572573

573574

575+
<h3><a name="fdw">Back to normal tables</a></h3>
576+
<p>
577+
As it was mentioned in previous section, <code>unnest</code> function can scatter records with VOPS types into normal records with scalar types.
578+
So it is possible to use this records in arbitrary SQL queries.
579+
But there are two problems with unnest function:
580+
</p>
581+
<ol>
582+
<li>It is not convenient to use. This function has no static knowledge about the format of output record and this is why programmer has to specify it manually,
583+
if here wants to decompose this record.</li>
584+
<li>PostgreSQL optimizer has completely no knowledge on result of transformation performed by unnest() function.
585+
This is why it is not able to choose optimal query execution plan for data retrieved from VOPS table.</li>
586+
</ol>
587+
<p>
588+
Fortunately Postgres provides solution for both of this problem: foreign data wrappers (FDW). In our case data is not really "foreign": it is stored inside our own database.
589+
But in alternatives (VOPS) format. VOPS FDW allows to "hide" specific of VOPS format and run normal SQL queries on VOPS tables.
590+
FDW allows the following:
591+
</p>
592+
<ol>
593+
<li>Extract data from VOPS table in normal (horizontal) format so that it can be proceeded by upper nodes in query execution plan.</li>
594+
<li>Pushdown to VOPS operations that can be efficiently executed using vectorized operations on VOPS types: filtering and aggregation.</li>
595+
<li>Provide statistic for underlying table which can be used by query optimizer.</li>
596+
</ol>
597+
598+
<p>
599+
So, by placing VOPS projection under FDW, we can efficiently perform sequential scan and aggregation queries as if them will be explicitly written for VOPS table
600+
and at the same time be able to execute any other queries on this data, including joins, CTEs,...
601+
Query can be written in standard SQL without usage of any VOPS specific functions.
602+
</p>
603+
604+
<p>
605+
Below is an example of creating VOPS FDW and running some queries on it:
606+
</p>
607+
608+
<pre>
609+
create foreign table lineitem_fdw (
610+
l_suppkey int4 not null,
611+
l_orderkey int4 not null,
612+
l_partkey int4 not null,
613+
l_shipdate date not null,
614+
l_quantity float4 not null,
615+
l_extendedprice float4 not null,
616+
l_discount float4 not null,
617+
l_tax float4 not null,
618+
l_returnflag "char" not null,
619+
l_linestatus "char" not null
620+
) server vops_server options (table_name 'vops_lineitem');
621+
622+
explain select
623+
sum(l_extendedprice*l_discount) as revenue
624+
from
625+
lineitem_fdw
626+
where
627+
l_shipdate between '1996-01-01' and '1997-01-01'
628+
and l_discount between 0.08 and 0.1
629+
and l_quantity < 24;
630+
QUERY PLAN
631+
---------------------------------------------------------
632+
Foreign Scan (cost=1903.26..1664020.23 rows=1 width=4)
633+
(1 row)
634+
635+
-- Filter was pushed down to FDW
636+
637+
explain select
638+
n_name,
639+
count(*),
640+
sum(l_extendedprice * (1-l_discount)) as revenue
641+
from
642+
customer_fdw join orders_fdw on c_custkey = o_custkey
643+
join lineitem_fdw on l_orderkey = o_orderkey
644+
join supplier_fdw on l_suppkey = s_suppkey
645+
join nation on c_nationkey = n_nationkey
646+
join region on n_regionkey = r_regionkey
647+
where
648+
c_nationkey = s_nationkey
649+
and r_name = 'ASIA'
650+
and o_orderdate >= '1996-01-01'
651+
and o_orderdate < '1997-01-01'
652+
group by
653+
n_name
654+
order by
655+
revenue desc;
656+
QUERY PLAN
657+
--------------------------------------------------------------------------------------------------------------------------------------
658+
Sort (cost=2337312.28..2337312.78 rows=200 width=48)
659+
Sort Key: (sum((lineitem_fdw.l_extendedprice * ('1'::double precision - lineitem_fdw.l_discount)))) DESC
660+
-> GroupAggregate (cost=2336881.54..2337304.64 rows=200 width=48)
661+
Group Key: nation.n_name
662+
-> Sort (cost=2336881.54..2336951.73 rows=28073 width=40)
663+
Sort Key: nation.n_name
664+
-> Hash Join (cost=396050.65..2334807.39 rows=28073 width=40)
665+
Hash Cond: ((orders_fdw.o_custkey = customer_fdw.c_custkey) AND (nation.n_nationkey = customer_fdw.c_nationkey))
666+
-> Hash Join (cost=335084.53..2247223.46 rows=701672 width=52)
667+
Hash Cond: (lineitem_fdw.l_orderkey = orders_fdw.o_orderkey)
668+
-> Hash Join (cost=2887.07..1786058.18 rows=4607421 width=52)
669+
Hash Cond: (lineitem_fdw.l_suppkey = supplier_fdw.s_suppkey)
670+
-> Foreign Scan on lineitem_fdw (cost=0.00..1512151.52 rows=59986176 width=16)
671+
-> Hash (cost=2790.80..2790.80 rows=7702 width=44)
672+
-> Hash Join (cost=40.97..2790.80 rows=7702 width=44)
673+
Hash Cond: (supplier_fdw.s_nationkey = nation.n_nationkey)
674+
-> Foreign Scan on supplier_fdw (cost=0.00..2174.64 rows=100032 width=8)
675+
-> Hash (cost=40.79..40.79 rows=15 width=36)
676+
-> Hash Join (cost=20.05..40.79 rows=15 width=36)
677+
Hash Cond: (nation.n_regionkey = region.r_regionkey)
678+
-> Seq Scan on nation (cost=0.00..17.70 rows=770 width=40)
679+
-> Hash (cost=20.00..20.00 rows=4 width=4)
680+
-> Seq Scan on region (cost=0.00..20.00 rows=4 width=4)
681+
Filter: ((r_name)::text = 'ASIA'::text)
682+
-> Hash (cost=294718.76..294718.76 rows=2284376 width=8)
683+
-> Foreign Scan on orders_fdw (cost=0.00..294718.76 rows=2284376 width=8)
684+
-> Hash (cost=32605.64..32605.64 rows=1500032 width=8)
685+
-> Foreign Scan on customer_fdw (cost=0.00..32605.64 rows=1500032 width=8)
686+
687+
-- filter on orders range is pushed to FDW
688+
</pre>
689+
690+
574691
<h2><a name="transform">Standard SQL query transformation</a></h2>
575692
<p>
576693
Previous section describes VOPS specific types, operators, functions,...

0 commit comments

Comments
 (0)