firtst release
Revision | 4c4f5cd40c357bb829e82005383cdadfc0245945 (tree) |
---|---|
Time | 2014-09-05 13:40:07 |
Author | Kyotaro Horiguchi <horiguchi.kyotaro@lab....> |
Commiter | Kyotaro Horiguchi |
Change verision to 1.1.1. Change target version to 9.4.
@@ -12,7 +12,7 @@ REGRESSION_EXPECTED = expected/init.out expected/base_plan.out expected/pg_hint_ | ||
12 | 12 | REGRESS_OPTS = --encoding=UTF8 |
13 | 13 | |
14 | 14 | EXTENSION = pg_hint_plan |
15 | -DATA = pg_hint_plan--1.0.sql | |
15 | +DATA = pg_hint_plan--1.1.1.sql | |
16 | 16 | |
17 | 17 | EXTRA_CLEAN = sql/ut-fdw.sql expected/ut-fdw.out |
18 | 18 |
@@ -23,4 +23,4 @@ include $(PGXS) | ||
23 | 23 | installcheck: $(REGRESSION_EXPECTED) |
24 | 24 | |
25 | 25 | # pg_hint_plan.c includes core.c and make_join_rel.c |
26 | -pg_hint_plan.o: core.c make_join_rel.c # pg_stat_statements.c | |
26 | +pg_hint_plan.o: core.c make_join_rel.c pg_stat_statements.c |
@@ -1,15 +1,15 @@ | ||
1 | 1 | # SPEC file for pg_hint_plan |
2 | 2 | # Copyright(C) 2012-2014 NIPPON TELEGRAPH AND TELEPHONE CORPORATION |
3 | 3 | |
4 | -%define _pgdir /usr/pgsql-9.3 | |
4 | +%define _pgdir /usr/pgsql-9.4 | |
5 | 5 | %define _bindir %{_pgdir}/bin |
6 | 6 | %define _libdir %{_pgdir}/lib |
7 | 7 | %define _datadir %{_pgdir}/share |
8 | 8 | |
9 | 9 | ## Set general information for pg_hint_plan. |
10 | -Summary: Optimizer hint for PostgreSQL 9.3 | |
11 | -Name: pg_hint_plan93 | |
12 | -Version: 1.1.0 | |
10 | +Summary: Optimizer hint for PostgreSQL 9.4 | |
11 | +Name: pg_hint_plan94 | |
12 | +Version: 1.1.1 | |
13 | 13 | Release: 1%{?dist} |
14 | 14 | License: BSD |
15 | 15 | Group: Applications/Databases |
@@ -19,8 +19,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n) | ||
19 | 19 | Vendor: NIPPON TELEGRAPH AND TELEPHONE CORPORATION |
20 | 20 | |
21 | 21 | ## We use postgresql-devel package |
22 | -BuildRequires: postgresql93-devel | |
23 | -Requires: postgresql93-libs | |
22 | +BuildRequires: postgresql94-devel | |
23 | +Requires: postgresql94-libs | |
24 | 24 | |
25 | 25 | ## Description for "pg_hint_plan" |
26 | 26 | %description |
@@ -32,7 +32,7 @@ plan by adding special comment block with optimizer hint before the query you | ||
32 | 32 | want to optimize. You can control scan method, join method, join order, and |
33 | 33 | planner-related GUC parameters during planning. |
34 | 34 | |
35 | -Note that this package is available for only PostgreSQL 9.3. | |
35 | +Note that this package is available for only PostgreSQL 9.4. | |
36 | 36 | |
37 | 37 | ## pre work for build pg_hint_plan |
38 | 38 | %prep |
@@ -48,7 +48,7 @@ rm -rf %{buildroot} | ||
48 | 48 | install -d %{buildroot}%{_libdir} |
49 | 49 | install pg_hint_plan.so %{buildroot}%{_libdir}/pg_hint_plan.so |
50 | 50 | install -d %{buildroot}%{_datadir}/extension |
51 | -install -m 644 pg_hint_plan--1.0.sql %{buildroot}%{_datadir}/extension/pg_hint_plan--1.0.sql | |
51 | +install -m 644 pg_hint_plan--1.1.1.sql %{buildroot}%{_datadir}/extension/pg_hint_plan--1.1.1.sql | |
52 | 52 | install -m 644 pg_hint_plan.control %{buildroot}%{_datadir}/extension/pg_hint_plan.control |
53 | 53 | |
54 | 54 | %clean |
@@ -58,11 +58,13 @@ rm -rf %{buildroot} | ||
58 | 58 | %defattr(0755,root,root) |
59 | 59 | %{_libdir}/pg_hint_plan.so |
60 | 60 | %defattr(0644,root,root) |
61 | -%{_datadir}/extension/pg_hint_plan--1.0.sql | |
61 | +%{_datadir}/extension/pg_hint_plan--1.1.1.sql | |
62 | 62 | %{_datadir}/extension/pg_hint_plan.control |
63 | 63 | |
64 | 64 | # History of pg_hint_plan. |
65 | 65 | %changelog |
66 | +* Thu Sep 14 2014 Kyotaro Horiguchi | |
67 | +- Support 9.4. Bug fix. New rev 1.1.1. | |
66 | 68 | * Mon Sep 02 2013 Takashi Suzuki |
67 | 69 | - Initial cut for 1.1.0 |
68 | 70 | * Mon Sep 24 2012 Shigeru Hanada <shigeru.hanada@gmail.com> |
@@ -4392,13 +4392,13 @@ error hint: | ||
4392 | 4392 | (9 rows) |
4393 | 4393 | |
4394 | 4394 | \o results/ut-R.tmpout |
4395 | -/*+ Leading(*VALUES* t1 t2) Rows(*VALUES* t1 #2)Rows(*VALUES* t1 t2 #2)*/ | |
4395 | +/*+ Leading(*VALUES* t1 t2) Rows(*VALUES* t1 #2)Rows(*VALUES* t1 t2 #20)*/ | |
4396 | 4396 | EXPLAIN SELECT * FROM s1.t1, s1.t2, (VALUES(1,1,1,'1')) AS t3 (c1, c2, c3, c4) WHERE t1.c1 = t2.c1 AND t1.c1 = t3.c1; |
4397 | 4397 | LOG: pg_hint_plan: |
4398 | 4398 | used hint: |
4399 | 4399 | Leading(*VALUES* t1 t2) |
4400 | 4400 | Rows(*VALUES* t1 #2) |
4401 | -Rows(*VALUES* t1 t2 #2) | |
4401 | +Rows(*VALUES* t1 t2 #20) | |
4402 | 4402 | not used hint: |
4403 | 4403 | duplication hint: |
4404 | 4404 | error hint: |
@@ -4407,7 +4407,7 @@ error hint: | ||
4407 | 4407 | \! sql/maskout.sh results/ut-R.tmpout |
4408 | 4408 | QUERY PLAN |
4409 | 4409 | ----------------------------------------------------------------------------- |
4410 | - Nested Loop (cost=xxx rows=1 width=xxx) | |
4410 | + Nested Loop (cost=xxx rows=20 width=xxx) | |
4411 | 4411 | -> Nested Loop (cost=xxx rows=2 width=xxx) |
4412 | 4412 | -> Values Scan on "*VALUES*" (cost=xxx rows=1 width=xxx) |
4413 | 4413 | -> Index Scan using t1_i1 on t1 (cost=xxx rows=1 width=xxx) |
@@ -13,6 +13,9 @@ | ||
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
15 | 15 | |
16 | +/* | |
17 | + * adjust_rows: tweak estimated row numbers according to the hint. | |
18 | +*/ | |
16 | 19 | static double |
17 | 20 | adjust_rows(double rows, RowsHint *hint) |
18 | 21 | { |
@@ -88,7 +91,7 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) | ||
88 | 91 | |
89 | 92 | /* |
90 | 93 | * If it's a plain inner join, then we won't have found anything in |
91 | - * join_info_list. Make up a SpecialJoinInfo so that selectivity | |
94 | + * join_info_list. Make up a SpecialJoinInfo so that selectivity | |
92 | 95 | * estimation functions will know what's being joined. |
93 | 96 | */ |
94 | 97 | if (sjinfo == NULL) |
@@ -114,67 +117,81 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) | ||
114 | 117 | &restrictlist); |
115 | 118 | |
116 | 119 | /* !!! START: HERE IS THE PART WHICH ADDED FOR PG_HINT_PLAN !!! */ |
117 | - { | |
118 | - RowsHint *rows_hint = NULL; | |
119 | - int i; | |
120 | - | |
121 | - /* Apply appropriate Rows hint to the join node, if any. */ | |
122 | - for (i = 0; i < current_hint->num_hints[HINT_TYPE_ROWS]; i++) | |
123 | 120 | { |
124 | - rows_hint = current_hint->rows_hints[i]; | |
121 | + RowsHint *rows_hint = NULL; | |
122 | + int i; | |
123 | + RowsHint *justforme = NULL; | |
124 | + RowsHint *domultiply = NULL; | |
125 | 125 | |
126 | - /* | |
127 | - * This Rows hint is invalid for some reason, or it contains no | |
128 | - * aliasname which exists in the query. | |
129 | - */ | |
130 | - if (!rows_hint->joinrelids || | |
131 | - rows_hint->base.state == HINT_STATE_ERROR) | |
132 | - continue; | |
133 | - | |
134 | - if (bms_equal(joinrelids, rows_hint->joinrelids)) | |
126 | + /* Search for applicable rows hint for this join node */ | |
127 | + for (i = 0; i < current_hint->num_hints[HINT_TYPE_ROWS]; i++) | |
135 | 128 | { |
129 | + rows_hint = current_hint->rows_hints[i]; | |
130 | + | |
136 | 131 | /* |
137 | - * This join RelOptInfo is exactly a Rows hint specifies, so adjust | |
138 | - * rows estimateion with the hint's content. Here we never have | |
139 | - * another hint which has same relation combination, so we can skip | |
140 | - * rest of hints. | |
132 | + * Skip this rows_hint if it is invalid from the first or it | |
133 | + * doesn't target any join rels. | |
141 | 134 | */ |
142 | - if (rows_hint->base.state == HINT_STATE_NOTUSED) | |
143 | - joinrel->rows = adjust_rows(joinrel->rows, rows_hint); | |
135 | + if (!rows_hint->joinrelids || | |
136 | + rows_hint->base.state == HINT_STATE_ERROR) | |
137 | + continue; | |
138 | + | |
139 | + if (bms_equal(joinrelids, rows_hint->joinrelids)) | |
140 | + { | |
141 | + /* | |
142 | + * This joinrel is just the target of this rows_hint, so tweak | |
143 | + * rows estimation according to the hint. | |
144 | + */ | |
145 | + justforme = rows_hint; | |
146 | + } | |
147 | + else if (!(bms_is_subset(rows_hint->joinrelids, rel1->relids) || | |
148 | + bms_is_subset(rows_hint->joinrelids, rel2->relids)) && | |
149 | + bms_is_subset(rows_hint->joinrelids, joinrelids) && | |
150 | + rows_hint->value_type == RVT_MULTI) | |
151 | + { | |
152 | + /* | |
153 | + * If the rows_hint's target relids is not a subset of both of | |
154 | + * component rels and is a subset of this joinrel, ths hint's | |
155 | + * targets spread over both component rels. This menas that | |
156 | + * this hint has been never applied so far and this joinrel is | |
157 | + * the first (and only) chance to fire in current join tree. | |
158 | + * Only the multiplication hint has the cumulative nature so we | |
159 | + * apply only RVT_MULTI in this way. | |
160 | + */ | |
161 | + domultiply = rows_hint; | |
162 | + } | |
144 | 163 | } |
145 | - else if (bms_is_subset(rows_hint->joinrelids, rel1->relids) || | |
146 | - bms_is_subset(rows_hint->joinrelids, rel2->relids)) | |
164 | + | |
165 | + if (justforme) | |
147 | 166 | { |
148 | 167 | /* |
149 | - * Otherwise if the relation combination specified in thee Rows | |
150 | - * hint is subset of the set of join elements, re-estimate rows and | |
151 | - * costs again to reflect the adjustment done in down. This is | |
152 | - * necessary for the first permutation of the combination the | |
153 | - * relations, but it's difficult to determine that this is the | |
154 | - * first, so do this everytime. | |
168 | + * If a hint just for me is found, no other adjust method is | |
169 | + * useles, but this cannot be more than twice becuase this joinrel | |
170 | + * is already adjusted by this hint. | |
155 | 171 | */ |
156 | - set_joinrel_size_estimates(root, joinrel, rel1, rel2, sjinfo, | |
157 | - restrictlist); | |
172 | + if (justforme->base.state == HINT_STATE_NOTUSED) | |
173 | + joinrel->rows = adjust_rows(joinrel->rows, justforme); | |
158 | 174 | } |
159 | - else if (bms_is_subset(rows_hint->joinrelids, joinrelids)) | |
175 | + else | |
160 | 176 | { |
161 | - /* | |
162 | - * If the combination specifed in the Rows hints is subset of the | |
163 | - * join relation and spreads over both children, | |
164 | - * | |
165 | - * We do adjust rows estimation only when the value type was | |
166 | - * multiplication, because other value types are meanless. | |
167 | - */ | |
168 | - if (rows_hint->value_type == RVT_MULTI) | |
177 | + if (domultiply) | |
169 | 178 | { |
179 | + /* | |
180 | + * If we have multiple routes up to this joinrel which are not | |
181 | + * applicable this hint, this multiply hint will applied more | |
182 | + * than twice. But there's no means to know of that, | |
183 | + * re-estimate the row number of this joinrel always just | |
184 | + * before applying the hint. This is a bit different from | |
185 | + * normal planner behavior but it doesn't harm so much. | |
186 | + */ | |
170 | 187 | set_joinrel_size_estimates(root, joinrel, rel1, rel2, sjinfo, |
171 | 188 | restrictlist); |
172 | - joinrel->rows = adjust_rows(joinrel->rows, rows_hint); | |
189 | + | |
190 | + joinrel->rows = adjust_rows(joinrel->rows, domultiply); | |
173 | 191 | } |
192 | + | |
174 | 193 | } |
175 | 194 | } |
176 | - | |
177 | - } | |
178 | 195 | /* !!! END: HERE IS THE PART WHICH ADDED FOR PG_HINT_PLAN !!! */ |
179 | 196 | |
180 | 197 | /* |
@@ -1,4 +1,4 @@ | ||
1 | -/* pg_hint_plan/pg_hint_plan--1.0.sql */ | |
1 | +/* pg_hint_plan/pg_hint_plan--1.1.1.sql */ | |
2 | 2 | |
3 | 3 | -- complain if script is sourced in psql, rather than via CREATE EXTENSION |
4 | 4 | \echo Use "CREATE EXTENSION pg_hint_plan" to load this file. \quit |
@@ -53,7 +53,7 @@ | ||
53 | 53 | /* partially copied from pg_stat_statements */ |
54 | 54 | #include "normalize_query.h" |
55 | 55 | |
56 | -/* PostgreSQL 9.3 */ | |
56 | +/* PostgreSQL */ | |
57 | 57 | #include "access/htup_details.h" |
58 | 58 | |
59 | 59 | #ifdef PG_MODULE_MAGIC |
@@ -3292,7 +3292,7 @@ transform_join_hints(HintState *hstate, PlannerInfo *root, int nbaserel, | ||
3292 | 3292 | return false; |
3293 | 3293 | |
3294 | 3294 | /* |
3295 | - * Decide to use Leading hint。 | |
3295 | + * Decide whether to use Leading hint | |
3296 | 3296 | */ |
3297 | 3297 | for (i = 0; i < hstate->num_hints[HINT_TYPE_LEADING]; i++) |
3298 | 3298 | { |
@@ -1,6 +1,6 @@ | ||
1 | 1 | # pg_hint_plan extension |
2 | 2 | |
3 | 3 | comment = '' |
4 | -default_version = '1.0' | |
4 | +default_version = '1.1.1' | |
5 | 5 | relocatable = false |
6 | 6 | schema = hint_plan |
@@ -1163,7 +1163,7 @@ EXPLAIN SELECT * FROM s1.t1, s1.t2, (VALUES(1,1,1,'1')) AS t3 (c1, c2, c3, c4) W | ||
1163 | 1163 | \! sql/maskout.sh results/ut-R.tmpout |
1164 | 1164 | |
1165 | 1165 | \o results/ut-R.tmpout |
1166 | -/*+ Leading(*VALUES* t1 t2) Rows(*VALUES* t1 #2)Rows(*VALUES* t1 t2 #2)*/ | |
1166 | +/*+ Leading(*VALUES* t1 t2) Rows(*VALUES* t1 #2)Rows(*VALUES* t1 t2 #20)*/ | |
1167 | 1167 | EXPLAIN SELECT * FROM s1.t1, s1.t2, (VALUES(1,1,1,'1')) AS t3 (c1, c2, c3, c4) WHERE t1.c1 = t2.c1 AND t1.c1 = t3.c1; |
1168 | 1168 | \o |
1169 | 1169 | \! sql/maskout.sh results/ut-R.tmpout |