1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * network_selfuncs.c |
4 | * Functions for selectivity estimation of inet/cidr operators |
5 | * |
6 | * This module provides estimators for the subnet inclusion and overlap |
7 | * operators. Estimates are based on null fraction, most common values, |
8 | * and histogram of inet/cidr columns. |
9 | * |
10 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
11 | * Portions Copyright (c) 1994, Regents of the University of California |
12 | * |
13 | * |
14 | * IDENTIFICATION |
15 | * src/backend/utils/adt/network_selfuncs.c |
16 | * |
17 | *------------------------------------------------------------------------- |
18 | */ |
19 | #include "postgres.h" |
20 | |
21 | #include <math.h> |
22 | |
23 | #include "access/htup_details.h" |
24 | #include "catalog/pg_operator.h" |
25 | #include "catalog/pg_statistic.h" |
26 | #include "utils/builtins.h" |
27 | #include "utils/inet.h" |
28 | #include "utils/lsyscache.h" |
29 | #include "utils/selfuncs.h" |
30 | |
31 | |
32 | /* Default selectivity for the inet overlap operator */ |
33 | #define DEFAULT_OVERLAP_SEL 0.01 |
34 | |
35 | /* Default selectivity for the various inclusion operators */ |
36 | #define DEFAULT_INCLUSION_SEL 0.005 |
37 | |
38 | /* Default selectivity for specified operator */ |
39 | #define DEFAULT_SEL(operator) \ |
40 | ((operator) == OID_INET_OVERLAP_OP ? \ |
41 | DEFAULT_OVERLAP_SEL : DEFAULT_INCLUSION_SEL) |
42 | |
43 | /* Maximum number of items to consider in join selectivity calculations */ |
44 | #define MAX_CONSIDERED_ELEMS 1024 |
45 | |
46 | static Selectivity networkjoinsel_inner(Oid operator, |
47 | VariableStatData *vardata1, VariableStatData *vardata2); |
48 | static Selectivity networkjoinsel_semi(Oid operator, |
49 | VariableStatData *vardata1, VariableStatData *vardata2); |
50 | static Selectivity mcv_population(float4 *mcv_numbers, int mcv_nvalues); |
51 | static Selectivity inet_hist_value_sel(Datum *values, int nvalues, |
52 | Datum constvalue, int opr_codenum); |
53 | static Selectivity inet_mcv_join_sel(Datum *mcv1_values, |
54 | float4 *mcv1_numbers, int mcv1_nvalues, Datum *mcv2_values, |
55 | float4 *mcv2_numbers, int mcv2_nvalues, Oid operator); |
56 | static Selectivity inet_mcv_hist_sel(Datum *mcv_values, float4 *mcv_numbers, |
57 | int mcv_nvalues, Datum *hist_values, int hist_nvalues, |
58 | int opr_codenum); |
59 | static Selectivity inet_hist_inclusion_join_sel(Datum *hist1_values, |
60 | int hist1_nvalues, |
61 | Datum *hist2_values, int hist2_nvalues, |
62 | int opr_codenum); |
63 | static Selectivity inet_semi_join_sel(Datum lhs_value, |
64 | bool mcv_exists, Datum *mcv_values, int mcv_nvalues, |
65 | bool hist_exists, Datum *hist_values, int hist_nvalues, |
66 | double hist_weight, |
67 | FmgrInfo *proc, int opr_codenum); |
68 | static int inet_opr_codenum(Oid operator); |
69 | static int inet_inclusion_cmp(inet *left, inet *right, int opr_codenum); |
70 | static int inet_masklen_inclusion_cmp(inet *left, inet *right, |
71 | int opr_codenum); |
72 | static int inet_hist_match_divider(inet *boundary, inet *query, |
73 | int opr_codenum); |
74 | |
75 | /* |
76 | * Selectivity estimation for the subnet inclusion/overlap operators |
77 | */ |
78 | Datum |
79 | networksel(PG_FUNCTION_ARGS) |
80 | { |
81 | PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); |
82 | Oid operator = PG_GETARG_OID(1); |
83 | List *args = (List *) PG_GETARG_POINTER(2); |
84 | int varRelid = PG_GETARG_INT32(3); |
85 | VariableStatData vardata; |
86 | Node *other; |
87 | bool varonleft; |
88 | Selectivity selec, |
89 | mcv_selec, |
90 | non_mcv_selec; |
91 | Datum constvalue; |
92 | Form_pg_statistic stats; |
93 | AttStatsSlot hslot; |
94 | double sumcommon, |
95 | nullfrac; |
96 | FmgrInfo proc; |
97 | |
98 | /* |
99 | * If expression is not (variable op something) or (something op |
100 | * variable), then punt and return a default estimate. |
101 | */ |
102 | if (!get_restriction_variable(root, args, varRelid, |
103 | &vardata, &other, &varonleft)) |
104 | PG_RETURN_FLOAT8(DEFAULT_SEL(operator)); |
105 | |
106 | /* |
107 | * Can't do anything useful if the something is not a constant, either. |
108 | */ |
109 | if (!IsA(other, Const)) |
110 | { |
111 | ReleaseVariableStats(vardata); |
112 | PG_RETURN_FLOAT8(DEFAULT_SEL(operator)); |
113 | } |
114 | |
115 | /* All of the operators handled here are strict. */ |
116 | if (((Const *) other)->constisnull) |
117 | { |
118 | ReleaseVariableStats(vardata); |
119 | PG_RETURN_FLOAT8(0.0); |
120 | } |
121 | constvalue = ((Const *) other)->constvalue; |
122 | |
123 | /* Otherwise, we need stats in order to produce a non-default estimate. */ |
124 | if (!HeapTupleIsValid(vardata.statsTuple)) |
125 | { |
126 | ReleaseVariableStats(vardata); |
127 | PG_RETURN_FLOAT8(DEFAULT_SEL(operator)); |
128 | } |
129 | |
130 | stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple); |
131 | nullfrac = stats->stanullfrac; |
132 | |
133 | /* |
134 | * If we have most-common-values info, add up the fractions of the MCV |
135 | * entries that satisfy MCV OP CONST. These fractions contribute directly |
136 | * to the result selectivity. Also add up the total fraction represented |
137 | * by MCV entries. |
138 | */ |
139 | fmgr_info(get_opcode(operator), &proc); |
140 | mcv_selec = mcv_selectivity(&vardata, &proc, constvalue, varonleft, |
141 | &sumcommon); |
142 | |
143 | /* |
144 | * If we have a histogram, use it to estimate the proportion of the |
145 | * non-MCV population that satisfies the clause. If we don't, apply the |
146 | * default selectivity to that population. |
147 | */ |
148 | if (get_attstatsslot(&hslot, vardata.statsTuple, |
149 | STATISTIC_KIND_HISTOGRAM, InvalidOid, |
150 | ATTSTATSSLOT_VALUES)) |
151 | { |
152 | int opr_codenum = inet_opr_codenum(operator); |
153 | |
154 | /* Commute if needed, so we can consider histogram to be on the left */ |
155 | if (!varonleft) |
156 | opr_codenum = -opr_codenum; |
157 | non_mcv_selec = inet_hist_value_sel(hslot.values, hslot.nvalues, |
158 | constvalue, opr_codenum); |
159 | |
160 | free_attstatsslot(&hslot); |
161 | } |
162 | else |
163 | non_mcv_selec = DEFAULT_SEL(operator); |
164 | |
165 | /* Combine selectivities for MCV and non-MCV populations */ |
166 | selec = mcv_selec + (1.0 - nullfrac - sumcommon) * non_mcv_selec; |
167 | |
168 | /* Result should be in range, but make sure... */ |
169 | CLAMP_PROBABILITY(selec); |
170 | |
171 | ReleaseVariableStats(vardata); |
172 | |
173 | PG_RETURN_FLOAT8(selec); |
174 | } |
175 | |
176 | /* |
177 | * Join selectivity estimation for the subnet inclusion/overlap operators |
178 | * |
179 | * This function has the same structure as eqjoinsel() in selfuncs.c. |
180 | * |
181 | * Throughout networkjoinsel and its subroutines, we have a performance issue |
182 | * in that the amount of work to be done is O(N^2) in the length of the MCV |
183 | * and histogram arrays. To keep the runtime from getting out of hand when |
184 | * large statistics targets have been set, we arbitrarily limit the number of |
185 | * values considered to 1024 (MAX_CONSIDERED_ELEMS). For the MCV arrays, this |
186 | * is easy: just consider at most the first N elements. (Since the MCVs are |
187 | * sorted by decreasing frequency, this correctly gets us the first N MCVs.) |
188 | * For the histogram arrays, we decimate; that is consider only every k'th |
189 | * element, where k is chosen so that no more than MAX_CONSIDERED_ELEMS |
190 | * elements are considered. This should still give us a good random sample of |
191 | * the non-MCV population. Decimation is done on-the-fly in the loops that |
192 | * iterate over the histogram arrays. |
193 | */ |
194 | Datum |
195 | networkjoinsel(PG_FUNCTION_ARGS) |
196 | { |
197 | PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); |
198 | Oid operator = PG_GETARG_OID(1); |
199 | List *args = (List *) PG_GETARG_POINTER(2); |
200 | #ifdef NOT_USED |
201 | JoinType jointype = (JoinType) PG_GETARG_INT16(3); |
202 | #endif |
203 | SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) PG_GETARG_POINTER(4); |
204 | double selec; |
205 | VariableStatData vardata1; |
206 | VariableStatData vardata2; |
207 | bool join_is_reversed; |
208 | |
209 | get_join_variables(root, args, sjinfo, |
210 | &vardata1, &vardata2, &join_is_reversed); |
211 | |
212 | switch (sjinfo->jointype) |
213 | { |
214 | case JOIN_INNER: |
215 | case JOIN_LEFT: |
216 | case JOIN_FULL: |
217 | |
218 | /* |
219 | * Selectivity for left/full join is not exactly the same as inner |
220 | * join, but we neglect the difference, as eqjoinsel does. |
221 | */ |
222 | selec = networkjoinsel_inner(operator, &vardata1, &vardata2); |
223 | break; |
224 | case JOIN_SEMI: |
225 | case JOIN_ANTI: |
226 | /* Here, it's important that we pass the outer var on the left. */ |
227 | if (!join_is_reversed) |
228 | selec = networkjoinsel_semi(operator, &vardata1, &vardata2); |
229 | else |
230 | selec = networkjoinsel_semi(get_commutator(operator), |
231 | &vardata2, &vardata1); |
232 | break; |
233 | default: |
234 | /* other values not expected here */ |
235 | elog(ERROR, "unrecognized join type: %d" , |
236 | (int) sjinfo->jointype); |
237 | selec = 0; /* keep compiler quiet */ |
238 | break; |
239 | } |
240 | |
241 | ReleaseVariableStats(vardata1); |
242 | ReleaseVariableStats(vardata2); |
243 | |
244 | CLAMP_PROBABILITY(selec); |
245 | |
246 | PG_RETURN_FLOAT8((float8) selec); |
247 | } |
248 | |
249 | /* |
250 | * Inner join selectivity estimation for subnet inclusion/overlap operators |
251 | * |
252 | * Calculates MCV vs MCV, MCV vs histogram and histogram vs histogram |
253 | * selectivity for join using the subnet inclusion operators. Unlike the |
254 | * join selectivity function for the equality operator, eqjoinsel_inner(), |
255 | * one to one matching of the values is not enough. Network inclusion |
256 | * operators are likely to match many to many, so we must check all pairs. |
257 | * (Note: it might be possible to exploit understanding of the histogram's |
258 | * btree ordering to reduce the work needed, but we don't currently try.) |
259 | * Also, MCV vs histogram selectivity is not neglected as in eqjoinsel_inner(). |
260 | */ |
261 | static Selectivity |
262 | networkjoinsel_inner(Oid operator, |
263 | VariableStatData *vardata1, VariableStatData *vardata2) |
264 | { |
265 | Form_pg_statistic stats; |
266 | double nullfrac1 = 0.0, |
267 | nullfrac2 = 0.0; |
268 | Selectivity selec = 0.0, |
269 | sumcommon1 = 0.0, |
270 | sumcommon2 = 0.0; |
271 | bool mcv1_exists = false, |
272 | mcv2_exists = false, |
273 | hist1_exists = false, |
274 | hist2_exists = false; |
275 | int opr_codenum; |
276 | int mcv1_length = 0, |
277 | mcv2_length = 0; |
278 | AttStatsSlot mcv1_slot; |
279 | AttStatsSlot mcv2_slot; |
280 | AttStatsSlot hist1_slot; |
281 | AttStatsSlot hist2_slot; |
282 | |
283 | if (HeapTupleIsValid(vardata1->statsTuple)) |
284 | { |
285 | stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple); |
286 | nullfrac1 = stats->stanullfrac; |
287 | |
288 | mcv1_exists = get_attstatsslot(&mcv1_slot, vardata1->statsTuple, |
289 | STATISTIC_KIND_MCV, InvalidOid, |
290 | ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS); |
291 | hist1_exists = get_attstatsslot(&hist1_slot, vardata1->statsTuple, |
292 | STATISTIC_KIND_HISTOGRAM, InvalidOid, |
293 | ATTSTATSSLOT_VALUES); |
294 | /* Arbitrarily limit number of MCVs considered */ |
295 | mcv1_length = Min(mcv1_slot.nvalues, MAX_CONSIDERED_ELEMS); |
296 | if (mcv1_exists) |
297 | sumcommon1 = mcv_population(mcv1_slot.numbers, mcv1_length); |
298 | } |
299 | else |
300 | { |
301 | memset(&mcv1_slot, 0, sizeof(mcv1_slot)); |
302 | memset(&hist1_slot, 0, sizeof(hist1_slot)); |
303 | } |
304 | |
305 | if (HeapTupleIsValid(vardata2->statsTuple)) |
306 | { |
307 | stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple); |
308 | nullfrac2 = stats->stanullfrac; |
309 | |
310 | mcv2_exists = get_attstatsslot(&mcv2_slot, vardata2->statsTuple, |
311 | STATISTIC_KIND_MCV, InvalidOid, |
312 | ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS); |
313 | hist2_exists = get_attstatsslot(&hist2_slot, vardata2->statsTuple, |
314 | STATISTIC_KIND_HISTOGRAM, InvalidOid, |
315 | ATTSTATSSLOT_VALUES); |
316 | /* Arbitrarily limit number of MCVs considered */ |
317 | mcv2_length = Min(mcv2_slot.nvalues, MAX_CONSIDERED_ELEMS); |
318 | if (mcv2_exists) |
319 | sumcommon2 = mcv_population(mcv2_slot.numbers, mcv2_length); |
320 | } |
321 | else |
322 | { |
323 | memset(&mcv2_slot, 0, sizeof(mcv2_slot)); |
324 | memset(&hist2_slot, 0, sizeof(hist2_slot)); |
325 | } |
326 | |
327 | opr_codenum = inet_opr_codenum(operator); |
328 | |
329 | /* |
330 | * Calculate selectivity for MCV vs MCV matches. |
331 | */ |
332 | if (mcv1_exists && mcv2_exists) |
333 | selec += inet_mcv_join_sel(mcv1_slot.values, mcv1_slot.numbers, |
334 | mcv1_length, |
335 | mcv2_slot.values, mcv2_slot.numbers, |
336 | mcv2_length, |
337 | operator); |
338 | |
339 | /* |
340 | * Add in selectivities for MCV vs histogram matches, scaling according to |
341 | * the fractions of the populations represented by the histograms. Note |
342 | * that the second case needs to commute the operator. |
343 | */ |
344 | if (mcv1_exists && hist2_exists) |
345 | selec += (1.0 - nullfrac2 - sumcommon2) * |
346 | inet_mcv_hist_sel(mcv1_slot.values, mcv1_slot.numbers, mcv1_length, |
347 | hist2_slot.values, hist2_slot.nvalues, |
348 | opr_codenum); |
349 | if (mcv2_exists && hist1_exists) |
350 | selec += (1.0 - nullfrac1 - sumcommon1) * |
351 | inet_mcv_hist_sel(mcv2_slot.values, mcv2_slot.numbers, mcv2_length, |
352 | hist1_slot.values, hist1_slot.nvalues, |
353 | -opr_codenum); |
354 | |
355 | /* |
356 | * Add in selectivity for histogram vs histogram matches, again scaling |
357 | * appropriately. |
358 | */ |
359 | if (hist1_exists && hist2_exists) |
360 | selec += (1.0 - nullfrac1 - sumcommon1) * |
361 | (1.0 - nullfrac2 - sumcommon2) * |
362 | inet_hist_inclusion_join_sel(hist1_slot.values, hist1_slot.nvalues, |
363 | hist2_slot.values, hist2_slot.nvalues, |
364 | opr_codenum); |
365 | |
366 | /* |
367 | * If useful statistics are not available then use the default estimate. |
368 | * We can apply null fractions if known, though. |
369 | */ |
370 | if ((!mcv1_exists && !hist1_exists) || (!mcv2_exists && !hist2_exists)) |
371 | selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator); |
372 | |
373 | /* Release stats. */ |
374 | free_attstatsslot(&mcv1_slot); |
375 | free_attstatsslot(&mcv2_slot); |
376 | free_attstatsslot(&hist1_slot); |
377 | free_attstatsslot(&hist2_slot); |
378 | |
379 | return selec; |
380 | } |
381 | |
382 | /* |
383 | * Semi join selectivity estimation for subnet inclusion/overlap operators |
384 | * |
385 | * Calculates MCV vs MCV, MCV vs histogram, histogram vs MCV, and histogram vs |
386 | * histogram selectivity for semi/anti join cases. |
387 | */ |
388 | static Selectivity |
389 | networkjoinsel_semi(Oid operator, |
390 | VariableStatData *vardata1, VariableStatData *vardata2) |
391 | { |
392 | Form_pg_statistic stats; |
393 | Selectivity selec = 0.0, |
394 | sumcommon1 = 0.0, |
395 | sumcommon2 = 0.0; |
396 | double nullfrac1 = 0.0, |
397 | nullfrac2 = 0.0, |
398 | hist2_weight = 0.0; |
399 | bool mcv1_exists = false, |
400 | mcv2_exists = false, |
401 | hist1_exists = false, |
402 | hist2_exists = false; |
403 | int opr_codenum; |
404 | FmgrInfo proc; |
405 | int i, |
406 | mcv1_length = 0, |
407 | mcv2_length = 0; |
408 | AttStatsSlot mcv1_slot; |
409 | AttStatsSlot mcv2_slot; |
410 | AttStatsSlot hist1_slot; |
411 | AttStatsSlot hist2_slot; |
412 | |
413 | if (HeapTupleIsValid(vardata1->statsTuple)) |
414 | { |
415 | stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple); |
416 | nullfrac1 = stats->stanullfrac; |
417 | |
418 | mcv1_exists = get_attstatsslot(&mcv1_slot, vardata1->statsTuple, |
419 | STATISTIC_KIND_MCV, InvalidOid, |
420 | ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS); |
421 | hist1_exists = get_attstatsslot(&hist1_slot, vardata1->statsTuple, |
422 | STATISTIC_KIND_HISTOGRAM, InvalidOid, |
423 | ATTSTATSSLOT_VALUES); |
424 | /* Arbitrarily limit number of MCVs considered */ |
425 | mcv1_length = Min(mcv1_slot.nvalues, MAX_CONSIDERED_ELEMS); |
426 | if (mcv1_exists) |
427 | sumcommon1 = mcv_population(mcv1_slot.numbers, mcv1_length); |
428 | } |
429 | else |
430 | { |
431 | memset(&mcv1_slot, 0, sizeof(mcv1_slot)); |
432 | memset(&hist1_slot, 0, sizeof(hist1_slot)); |
433 | } |
434 | |
435 | if (HeapTupleIsValid(vardata2->statsTuple)) |
436 | { |
437 | stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple); |
438 | nullfrac2 = stats->stanullfrac; |
439 | |
440 | mcv2_exists = get_attstatsslot(&mcv2_slot, vardata2->statsTuple, |
441 | STATISTIC_KIND_MCV, InvalidOid, |
442 | ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS); |
443 | hist2_exists = get_attstatsslot(&hist2_slot, vardata2->statsTuple, |
444 | STATISTIC_KIND_HISTOGRAM, InvalidOid, |
445 | ATTSTATSSLOT_VALUES); |
446 | /* Arbitrarily limit number of MCVs considered */ |
447 | mcv2_length = Min(mcv2_slot.nvalues, MAX_CONSIDERED_ELEMS); |
448 | if (mcv2_exists) |
449 | sumcommon2 = mcv_population(mcv2_slot.numbers, mcv2_length); |
450 | } |
451 | else |
452 | { |
453 | memset(&mcv2_slot, 0, sizeof(mcv2_slot)); |
454 | memset(&hist2_slot, 0, sizeof(hist2_slot)); |
455 | } |
456 | |
457 | opr_codenum = inet_opr_codenum(operator); |
458 | fmgr_info(get_opcode(operator), &proc); |
459 | |
460 | /* Estimate number of input rows represented by RHS histogram. */ |
461 | if (hist2_exists && vardata2->rel) |
462 | hist2_weight = (1.0 - nullfrac2 - sumcommon2) * vardata2->rel->rows; |
463 | |
464 | /* |
465 | * Consider each element of the LHS MCV list, matching it to whatever RHS |
466 | * stats we have. Scale according to the known frequency of the MCV. |
467 | */ |
468 | if (mcv1_exists && (mcv2_exists || hist2_exists)) |
469 | { |
470 | for (i = 0; i < mcv1_length; i++) |
471 | { |
472 | selec += mcv1_slot.numbers[i] * |
473 | inet_semi_join_sel(mcv1_slot.values[i], |
474 | mcv2_exists, mcv2_slot.values, mcv2_length, |
475 | hist2_exists, |
476 | hist2_slot.values, hist2_slot.nvalues, |
477 | hist2_weight, |
478 | &proc, opr_codenum); |
479 | } |
480 | } |
481 | |
482 | /* |
483 | * Consider each element of the LHS histogram, except for the first and |
484 | * last elements, which we exclude on the grounds that they're outliers |
485 | * and thus not very representative. Scale on the assumption that each |
486 | * such histogram element represents an equal share of the LHS histogram |
487 | * population (which is a bit bogus, because the members of its bucket may |
488 | * not all act the same with respect to the join clause, but it's hard to |
489 | * do better). |
490 | * |
491 | * If there are too many histogram elements, decimate to limit runtime. |
492 | */ |
493 | if (hist1_exists && hist1_slot.nvalues > 2 && (mcv2_exists || hist2_exists)) |
494 | { |
495 | double hist_selec_sum = 0.0; |
496 | int k, |
497 | n; |
498 | |
499 | k = (hist1_slot.nvalues - 3) / MAX_CONSIDERED_ELEMS + 1; |
500 | |
501 | n = 0; |
502 | for (i = 1; i < hist1_slot.nvalues - 1; i += k) |
503 | { |
504 | hist_selec_sum += |
505 | inet_semi_join_sel(hist1_slot.values[i], |
506 | mcv2_exists, mcv2_slot.values, mcv2_length, |
507 | hist2_exists, |
508 | hist2_slot.values, hist2_slot.nvalues, |
509 | hist2_weight, |
510 | &proc, opr_codenum); |
511 | n++; |
512 | } |
513 | |
514 | selec += (1.0 - nullfrac1 - sumcommon1) * hist_selec_sum / n; |
515 | } |
516 | |
517 | /* |
518 | * If useful statistics are not available then use the default estimate. |
519 | * We can apply null fractions if known, though. |
520 | */ |
521 | if ((!mcv1_exists && !hist1_exists) || (!mcv2_exists && !hist2_exists)) |
522 | selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator); |
523 | |
524 | /* Release stats. */ |
525 | free_attstatsslot(&mcv1_slot); |
526 | free_attstatsslot(&mcv2_slot); |
527 | free_attstatsslot(&hist1_slot); |
528 | free_attstatsslot(&hist2_slot); |
529 | |
530 | return selec; |
531 | } |
532 | |
533 | /* |
534 | * Compute the fraction of a relation's population that is represented |
535 | * by the MCV list. |
536 | */ |
537 | static Selectivity |
538 | mcv_population(float4 *mcv_numbers, int mcv_nvalues) |
539 | { |
540 | Selectivity sumcommon = 0.0; |
541 | int i; |
542 | |
543 | for (i = 0; i < mcv_nvalues; i++) |
544 | { |
545 | sumcommon += mcv_numbers[i]; |
546 | } |
547 | |
548 | return sumcommon; |
549 | } |
550 | |
551 | /* |
552 | * Inet histogram vs single value selectivity estimation |
553 | * |
554 | * Estimate the fraction of the histogram population that satisfies |
555 | * "value OPR CONST". (The result needs to be scaled to reflect the |
556 | * proportion of the total population represented by the histogram.) |
557 | * |
558 | * The histogram is originally for the inet btree comparison operators. |
559 | * Only the common bits of the network part and the length of the network part |
560 | * (masklen) are interesting for the subnet inclusion operators. Fortunately, |
561 | * btree comparison treats the network part as the major sort key. Even so, |
562 | * the length of the network part would not really be significant in the |
563 | * histogram. This would lead to big mistakes for data sets with uneven |
564 | * masklen distribution. To reduce this problem, comparisons with the left |
565 | * and the right sides of the buckets are used together. |
566 | * |
567 | * Histogram bucket matches are calculated in two forms. If the constant |
568 | * matches both bucket endpoints the bucket is considered as fully matched. |
569 | * The second form is to match the bucket partially; we recognize this when |
570 | * the constant matches just one endpoint, or the two endpoints fall on |
571 | * opposite sides of the constant. (Note that when the constant matches an |
572 | * interior histogram element, it gets credit for partial matches to the |
573 | * buckets on both sides, while a match to a histogram endpoint gets credit |
574 | * for only one partial match. This is desirable.) |
575 | * |
576 | * The divider in the partial bucket match is imagined as the distance |
577 | * between the decisive bits and the common bits of the addresses. It will |
578 | * be used as a power of two as it is the natural scale for the IP network |
579 | * inclusion. This partial bucket match divider calculation is an empirical |
580 | * formula and subject to change with more experiment. |
581 | * |
582 | * For a partial match, we try to calculate dividers for both of the |
583 | * boundaries. If the address family of a boundary value does not match the |
584 | * constant or comparison of the length of the network parts is not correct |
585 | * for the operator, the divider for that boundary will not be taken into |
586 | * account. If both of the dividers are valid, the greater one will be used |
587 | * to minimize the mistake in buckets that have disparate masklens. This |
588 | * calculation is unfair when dividers can be calculated for both of the |
589 | * boundaries but they are far from each other; but it is not a common |
590 | * situation as the boundaries are expected to share most of their significant |
591 | * bits of their masklens. The mistake would be greater, if we would use the |
592 | * minimum instead of the maximum, and we don't know a sensible way to combine |
593 | * them. |
594 | * |
595 | * For partial match in buckets that have different address families on the |
596 | * left and right sides, only the boundary with the same address family is |
597 | * taken into consideration. This can cause more mistakes for these buckets |
598 | * if the masklens of their boundaries are also disparate. But this can only |
599 | * happen in one bucket, since only two address families exist. It seems a |
600 | * better option than not considering these buckets at all. |
601 | */ |
602 | static Selectivity |
603 | inet_hist_value_sel(Datum *values, int nvalues, Datum constvalue, |
604 | int opr_codenum) |
605 | { |
606 | Selectivity match = 0.0; |
607 | inet *query, |
608 | *left, |
609 | *right; |
610 | int i, |
611 | k, |
612 | n; |
613 | int left_order, |
614 | right_order, |
615 | left_divider, |
616 | right_divider; |
617 | |
618 | /* guard against zero-divide below */ |
619 | if (nvalues <= 1) |
620 | return 0.0; |
621 | |
622 | /* if there are too many histogram elements, decimate to limit runtime */ |
623 | k = (nvalues - 2) / MAX_CONSIDERED_ELEMS + 1; |
624 | |
625 | query = DatumGetInetPP(constvalue); |
626 | |
627 | /* "left" is the left boundary value of the current bucket ... */ |
628 | left = DatumGetInetPP(values[0]); |
629 | left_order = inet_inclusion_cmp(left, query, opr_codenum); |
630 | |
631 | n = 0; |
632 | for (i = k; i < nvalues; i += k) |
633 | { |
634 | /* ... and "right" is the right boundary value */ |
635 | right = DatumGetInetPP(values[i]); |
636 | right_order = inet_inclusion_cmp(right, query, opr_codenum); |
637 | |
638 | if (left_order == 0 && right_order == 0) |
639 | { |
640 | /* The whole bucket matches, since both endpoints do. */ |
641 | match += 1.0; |
642 | } |
643 | else if ((left_order <= 0 && right_order >= 0) || |
644 | (left_order >= 0 && right_order <= 0)) |
645 | { |
646 | /* Partial bucket match. */ |
647 | left_divider = inet_hist_match_divider(left, query, opr_codenum); |
648 | right_divider = inet_hist_match_divider(right, query, opr_codenum); |
649 | |
650 | if (left_divider >= 0 || right_divider >= 0) |
651 | match += 1.0 / pow(2.0, Max(left_divider, right_divider)); |
652 | } |
653 | |
654 | /* Shift the variables. */ |
655 | left = right; |
656 | left_order = right_order; |
657 | |
658 | /* Count the number of buckets considered. */ |
659 | n++; |
660 | } |
661 | |
662 | return match / n; |
663 | } |
664 | |
665 | /* |
666 | * Inet MCV vs MCV join selectivity estimation |
667 | * |
668 | * We simply add up the fractions of the populations that satisfy the clause. |
669 | * The result is exact and does not need to be scaled further. |
670 | */ |
671 | static Selectivity |
672 | inet_mcv_join_sel(Datum *mcv1_values, float4 *mcv1_numbers, int mcv1_nvalues, |
673 | Datum *mcv2_values, float4 *mcv2_numbers, int mcv2_nvalues, |
674 | Oid operator) |
675 | { |
676 | Selectivity selec = 0.0; |
677 | FmgrInfo proc; |
678 | int i, |
679 | j; |
680 | |
681 | fmgr_info(get_opcode(operator), &proc); |
682 | |
683 | for (i = 0; i < mcv1_nvalues; i++) |
684 | { |
685 | for (j = 0; j < mcv2_nvalues; j++) |
686 | if (DatumGetBool(FunctionCall2(&proc, |
687 | mcv1_values[i], |
688 | mcv2_values[j]))) |
689 | selec += mcv1_numbers[i] * mcv2_numbers[j]; |
690 | } |
691 | return selec; |
692 | } |
693 | |
694 | /* |
695 | * Inet MCV vs histogram join selectivity estimation |
696 | * |
697 | * For each MCV on the lefthand side, estimate the fraction of the righthand's |
698 | * histogram population that satisfies the join clause, and add those up, |
699 | * scaling by the MCV's frequency. The result still needs to be scaled |
700 | * according to the fraction of the righthand's population represented by |
701 | * the histogram. |
702 | */ |
703 | static Selectivity |
704 | inet_mcv_hist_sel(Datum *mcv_values, float4 *mcv_numbers, int mcv_nvalues, |
705 | Datum *hist_values, int hist_nvalues, |
706 | int opr_codenum) |
707 | { |
708 | Selectivity selec = 0.0; |
709 | int i; |
710 | |
711 | /* |
712 | * We'll call inet_hist_value_selec with the histogram on the left, so we |
713 | * must commute the operator. |
714 | */ |
715 | opr_codenum = -opr_codenum; |
716 | |
717 | for (i = 0; i < mcv_nvalues; i++) |
718 | { |
719 | selec += mcv_numbers[i] * |
720 | inet_hist_value_sel(hist_values, hist_nvalues, mcv_values[i], |
721 | opr_codenum); |
722 | } |
723 | return selec; |
724 | } |
725 | |
726 | /* |
727 | * Inet histogram vs histogram join selectivity estimation |
728 | * |
729 | * Here, we take all values listed in the second histogram (except for the |
730 | * first and last elements, which are excluded on the grounds of possibly |
731 | * not being very representative) and treat them as a uniform sample of |
732 | * the non-MCV population for that relation. For each one, we apply |
733 | * inet_hist_value_selec to see what fraction of the first histogram |
734 | * it matches. |
735 | * |
736 | * We could alternatively do this the other way around using the operator's |
737 | * commutator. XXX would it be worthwhile to do it both ways and take the |
738 | * average? That would at least avoid non-commutative estimation results. |
739 | */ |
740 | static Selectivity |
741 | inet_hist_inclusion_join_sel(Datum *hist1_values, int hist1_nvalues, |
742 | Datum *hist2_values, int hist2_nvalues, |
743 | int opr_codenum) |
744 | { |
745 | double match = 0.0; |
746 | int i, |
747 | k, |
748 | n; |
749 | |
750 | if (hist2_nvalues <= 2) |
751 | return 0.0; /* no interior histogram elements */ |
752 | |
753 | /* if there are too many histogram elements, decimate to limit runtime */ |
754 | k = (hist2_nvalues - 3) / MAX_CONSIDERED_ELEMS + 1; |
755 | |
756 | n = 0; |
757 | for (i = 1; i < hist2_nvalues - 1; i += k) |
758 | { |
759 | match += inet_hist_value_sel(hist1_values, hist1_nvalues, |
760 | hist2_values[i], opr_codenum); |
761 | n++; |
762 | } |
763 | |
764 | return match / n; |
765 | } |
766 | |
767 | /* |
768 | * Inet semi join selectivity estimation for one value |
769 | * |
770 | * The function calculates the probability that there is at least one row |
771 | * in the RHS table that satisfies the "lhs_value op column" condition. |
772 | * It is used in semi join estimation to check a sample from the left hand |
773 | * side table. |
774 | * |
775 | * The MCV and histogram from the right hand side table should be provided as |
776 | * arguments with the lhs_value from the left hand side table for the join. |
777 | * hist_weight is the total number of rows represented by the histogram. |
778 | * For example, if the table has 1000 rows, and 10% of the rows are in the MCV |
779 | * list, and another 10% are NULLs, hist_weight would be 800. |
780 | * |
781 | * First, the lhs_value will be matched to the most common values. If it |
782 | * matches any of them, 1.0 will be returned, because then there is surely |
783 | * a match. |
784 | * |
785 | * Otherwise, the histogram will be used to estimate the number of rows in |
786 | * the second table that match the condition. If the estimate is greater |
787 | * than 1.0, 1.0 will be returned, because it means there is a greater chance |
788 | * that the lhs_value will match more than one row in the table. If it is |
789 | * between 0.0 and 1.0, it will be returned as the probability. |
790 | */ |
791 | static Selectivity |
792 | inet_semi_join_sel(Datum lhs_value, |
793 | bool mcv_exists, Datum *mcv_values, int mcv_nvalues, |
794 | bool hist_exists, Datum *hist_values, int hist_nvalues, |
795 | double hist_weight, |
796 | FmgrInfo *proc, int opr_codenum) |
797 | { |
798 | if (mcv_exists) |
799 | { |
800 | int i; |
801 | |
802 | for (i = 0; i < mcv_nvalues; i++) |
803 | { |
804 | if (DatumGetBool(FunctionCall2(proc, |
805 | lhs_value, |
806 | mcv_values[i]))) |
807 | return 1.0; |
808 | } |
809 | } |
810 | |
811 | if (hist_exists && hist_weight > 0) |
812 | { |
813 | Selectivity hist_selec; |
814 | |
815 | /* Commute operator, since we're passing lhs_value on the right */ |
816 | hist_selec = inet_hist_value_sel(hist_values, hist_nvalues, |
817 | lhs_value, -opr_codenum); |
818 | |
819 | if (hist_selec > 0) |
820 | return Min(1.0, hist_weight * hist_selec); |
821 | } |
822 | |
823 | return 0.0; |
824 | } |
825 | |
826 | /* |
827 | * Assign useful code numbers for the subnet inclusion/overlap operators |
828 | * |
829 | * Only inet_masklen_inclusion_cmp() and inet_hist_match_divider() depend |
830 | * on the exact codes assigned here; but many other places in this file |
831 | * know that they can negate a code to obtain the code for the commutator |
832 | * operator. |
833 | */ |
834 | static int |
835 | inet_opr_codenum(Oid operator) |
836 | { |
837 | switch (operator) |
838 | { |
839 | case OID_INET_SUP_OP: |
840 | return -2; |
841 | case OID_INET_SUPEQ_OP: |
842 | return -1; |
843 | case OID_INET_OVERLAP_OP: |
844 | return 0; |
845 | case OID_INET_SUBEQ_OP: |
846 | return 1; |
847 | case OID_INET_SUB_OP: |
848 | return 2; |
849 | default: |
850 | elog(ERROR, "unrecognized operator %u for inet selectivity" , |
851 | operator); |
852 | } |
853 | return 0; /* unreached, but keep compiler quiet */ |
854 | } |
855 | |
856 | /* |
857 | * Comparison function for the subnet inclusion/overlap operators |
858 | * |
859 | * If the comparison is okay for the specified inclusion operator, the return |
860 | * value will be 0. Otherwise the return value will be less than or greater |
861 | * than 0 as appropriate for the operator. |
862 | * |
863 | * Comparison is compatible with the basic comparison function for the inet |
864 | * type. See network_cmp_internal() in network.c for the original. Basic |
865 | * comparison operators are implemented with the network_cmp_internal() |
866 | * function. It is possible to implement the subnet inclusion operators with |
867 | * this function. |
868 | * |
869 | * Comparison is first on the common bits of the network part, then on the |
870 | * length of the network part (masklen) as in the network_cmp_internal() |
871 | * function. Only the first part is in this function. The second part is |
872 | * separated to another function for reusability. The difference between the |
873 | * second part and the original network_cmp_internal() is that the inclusion |
874 | * operator is considered while comparing the lengths of the network parts. |
875 | * See the inet_masklen_inclusion_cmp() function below. |
876 | */ |
877 | static int |
878 | inet_inclusion_cmp(inet *left, inet *right, int opr_codenum) |
879 | { |
880 | if (ip_family(left) == ip_family(right)) |
881 | { |
882 | int order; |
883 | |
884 | order = bitncmp(ip_addr(left), ip_addr(right), |
885 | Min(ip_bits(left), ip_bits(right))); |
886 | if (order != 0) |
887 | return order; |
888 | |
889 | return inet_masklen_inclusion_cmp(left, right, opr_codenum); |
890 | } |
891 | |
892 | return ip_family(left) - ip_family(right); |
893 | } |
894 | |
895 | /* |
896 | * Masklen comparison function for the subnet inclusion/overlap operators |
897 | * |
898 | * Compares the lengths of the network parts of the inputs. If the comparison |
899 | * is okay for the specified inclusion operator, the return value will be 0. |
900 | * Otherwise the return value will be less than or greater than 0 as |
901 | * appropriate for the operator. |
902 | */ |
903 | static int |
904 | inet_masklen_inclusion_cmp(inet *left, inet *right, int opr_codenum) |
905 | { |
906 | int order; |
907 | |
908 | order = (int) ip_bits(left) - (int) ip_bits(right); |
909 | |
910 | /* |
911 | * Return 0 if the operator would accept this combination of masklens. |
912 | * Note that opr_codenum zero (overlaps) will accept all cases. |
913 | */ |
914 | if ((order > 0 && opr_codenum >= 0) || |
915 | (order == 0 && opr_codenum >= -1 && opr_codenum <= 1) || |
916 | (order < 0 && opr_codenum <= 0)) |
917 | return 0; |
918 | |
919 | /* |
920 | * Otherwise, return a negative value for sup/supeq (notionally, the RHS |
921 | * needs to have a larger masklen than it has, which would make it sort |
922 | * later), or a positive value for sub/subeq (vice versa). |
923 | */ |
924 | return opr_codenum; |
925 | } |
926 | |
927 | /* |
928 | * Inet histogram partial match divider calculation |
929 | * |
930 | * First the families and the lengths of the network parts are compared using |
931 | * the subnet inclusion operator. If those are acceptable for the operator, |
932 | * the divider will be calculated using the masklens and the common bits of |
933 | * the addresses. -1 will be returned if it cannot be calculated. |
934 | * |
935 | * See commentary for inet_hist_value_sel() for some rationale for this. |
936 | */ |
937 | static int |
938 | inet_hist_match_divider(inet *boundary, inet *query, int opr_codenum) |
939 | { |
940 | if (ip_family(boundary) == ip_family(query) && |
941 | inet_masklen_inclusion_cmp(boundary, query, opr_codenum) == 0) |
942 | { |
943 | int min_bits, |
944 | decisive_bits; |
945 | |
946 | min_bits = Min(ip_bits(boundary), ip_bits(query)); |
947 | |
948 | /* |
949 | * Set decisive_bits to the masklen of the one that should contain the |
950 | * other according to the operator. |
951 | */ |
952 | if (opr_codenum < 0) |
953 | decisive_bits = ip_bits(boundary); |
954 | else if (opr_codenum > 0) |
955 | decisive_bits = ip_bits(query); |
956 | else |
957 | decisive_bits = min_bits; |
958 | |
959 | /* |
960 | * Now return the number of non-common decisive bits. (This will be |
961 | * zero if the boundary and query in fact match, else positive.) |
962 | */ |
963 | if (min_bits > 0) |
964 | return decisive_bits - bitncommon(ip_addr(boundary), |
965 | ip_addr(query), |
966 | min_bits); |
967 | return decisive_bits; |
968 | } |
969 | |
970 | return -1; |
971 | } |
972 | |