Skip to content

Commit dbd80c9

Browse files
committed
Optimizer fix for samekeys() and cost fixes for longer optimizer keys.
1 parent 403b3ef commit dbd80c9

File tree

3 files changed

+64
-37
lines changed

3 files changed

+64
-37
lines changed

src/backend/optimizer/util/keys.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.14 1999/02/10 21:02:41 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.15 1999/02/11 04:08:42 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -106,7 +106,7 @@ extract_join_subkey(JoinKey *jk, int which_subkey)
106106
}
107107

108108
/*
109-
* samekeys--
109+
* pathkeys_match--
110110
* Returns t iff two sets of path keys are equivalent. They are
111111
* equivalent if the first Var nodes match the second Var nodes.
112112
*
@@ -118,7 +118,7 @@ extract_join_subkey(JoinKey *jk, int which_subkey)
118118
*
119119
*/
120120
bool
121-
samekeys(List *keys1, List *keys2)
121+
pathkeys_match(List *keys1, List *keys2, int *longer_key)
122122
{
123123
List *key1,
124124
*key2,
@@ -133,20 +133,39 @@ samekeys(List *keys1, List *keys2)
133133
key1a != NIL && key2a != NIL;
134134
key1a = lnext(key1a), key2a = lnext(key2a))
135135
if (!equal(lfirst(key1a), lfirst(key2a)))
136+
{
137+
*longer_key = 0;
136138
return false;
137-
if (key1a != NIL)
138-
return false;
139+
}
140+
if (key1a != NIL && key2a == NIL)
141+
{
142+
*longer_key = 1;
143+
return true;
144+
}
145+
if (key1a == NIL && key2a != NIL)
146+
{
147+
*longer_key = 2;
148+
return true;
149+
}
139150
}
140151

141152
/* Now the result should be true if list keys2 has at least as many
142153
* entries as keys1, ie, we did not fall off the end of keys2 first.
143154
* If key1 is now NIL then we hit the end of keys1 before or at the
144155
* same time as the end of keys2.
145156
*/
146-
if (key1 == NIL)
157+
if (key1 != NIL && key2 == NIL)
158+
{
159+
*longer_key = 1;
147160
return true;
148-
else
149-
return false;
161+
}
162+
if (key1 == NIL && key2 != NIL)
163+
{
164+
*longer_key = 2;
165+
return true;
166+
}
167+
*longer_key = 0;
168+
return true;
150169
}
151170

152171
/*

src/backend/optimizer/util/pathnode.c

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.23 1999/02/10 21:02:43 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.24 1999/02/11 04:08:43 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -29,7 +29,7 @@
2929

3030
#include "parser/parsetree.h" /* for getrelid() */
3131

32-
static Path *better_path(Path *new_path, List *unique_paths, bool *noOther);
32+
static Path *better_path(Path *new_path, List *unique_paths, bool *isNew);
3333

3434

3535
/*****************************************************************************
@@ -107,16 +107,16 @@ add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths)
107107
{
108108
Path *new_path = (Path *) lfirst(p1);
109109
Path *old_path;
110-
bool noOther;
110+
bool is_new;
111111

112112
/* Is this new path already in unique_paths? */
113113
if (member(new_path, unique_paths))
114114
continue;
115115

116116
/* Find best matching path */
117-
old_path = better_path(new_path, unique_paths, &noOther);
117+
old_path = better_path(new_path, unique_paths, &is_new);
118118

119-
if (noOther)
119+
if (is_new)
120120
{
121121
/* This is a brand new path. */
122122
new_path->parent = parent_rel;
@@ -153,19 +153,19 @@ add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths)
153153
*
154154
*/
155155
static Path *
156-
better_path(Path *new_path, List *unique_paths, bool *noOther)
156+
better_path(Path *new_path, List *unique_paths, bool *is_new)
157157
{
158-
Path *old_path = (Path *) NULL;
159158
Path *path = (Path *) NULL;
160159
List *temp = NIL;
161-
Path *retval = NULL;
160+
int longer_key;
162161

163162
foreach(temp, unique_paths)
164163
{
165164
path = (Path *) lfirst(temp);
166165

167166
#ifdef OPTDUP_DEBUG
168-
if (!samekeys(path->pathkeys, new_path->pathkeys))
167+
if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &longer_key) ||
168+
longer_key != 0)
169169
{
170170
printf("oldpath\n");
171171
pprint(path->pathkeys);
@@ -176,35 +176,43 @@ better_path(Path *new_path, List *unique_paths, bool *noOther)
176176
length(lfirst(path->pathkeys)) < length(lfirst(new_path->pathkeys)))
177177
sleep(0); /* set breakpoint here */
178178
}
179-
if (!equal_path_ordering(path->path_order,
180-
new_path->path_order))
179+
if (!equal_path_ordering(new_path->path_order, path->path_order))
181180
{
182181
printf("oldord\n");
183182
pprint(path->path_order);
184183
printf("neword\n");
185184
pprint(new_path->path_order);
186185
}
187186
#endif
188-
189-
if (samekeys(path->pathkeys, new_path->pathkeys) &&
190-
equal_path_ordering(path->path_order,
191-
new_path->path_order))
187+
188+
if (pathkeys_match(new_path->pathkeys, path->pathkeys, &longer_key))
192189
{
193-
old_path = path;
194-
break;
190+
if (equal_path_ordering(new_path->path_order, path->path_order))
191+
{
192+
/*
193+
* Replace pathkeys that match exactly, (1,2), (1,2).
194+
* Replace pathkeys (1,2) with (1,2,3) if the latter is not
195+
* more expensive and replace unordered path with ordered
196+
* path if it is not more expensive.
197+
*/
198+
if ((longer_key == 0 && new_path->path_cost < path->path_cost) ||
199+
(longer_key == 1 && new_path->path_cost <= path->path_cost) ||
200+
(longer_key == 2 && new_path->path_cost >= path->path_cost))
201+
{
202+
*is_new = false;
203+
return new_path;
204+
}
205+
else
206+
{
207+
*is_new = false;
208+
return NULL;
209+
}
210+
}
195211
}
196212
}
197213

198-
if (old_path == NULL)
199-
*noOther = true;
200-
else
201-
{
202-
*noOther = false;
203-
if (path_is_cheaper(new_path, old_path))
204-
retval = old_path;
205-
}
206-
207-
return retval;
214+
*is_new = true;
215+
return NULL;
208216
}
209217

210218

src/include/optimizer/keys.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: keys.h,v 1.9 1999/02/10 21:02:48 momjian Exp $
9+
* $Id: keys.h,v 1.10 1999/02/11 04:08:44 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -18,7 +18,7 @@
1818

1919
extern bool match_indexkey_operand(int indexkey, Var *operand, RelOptInfo *rel);
2020
extern Var *extract_join_subkey(JoinKey *jk, int which_subkey);
21-
extern bool samekeys(List *keys1, List *keys2);
21+
extern bool pathkeys_match(List *keys1, List *keys2, int *longer_key);
2222
extern List *collect_index_pathkeys(int *index_keys, List *tlist);
2323

2424
#endif /* KEYS_H */

0 commit comments

Comments
 (0)