@@ -356,55 +356,79 @@ class Optimizer : public Firebird::PermanentStorage
356
356
357
357
static double getSelectivity (const BoolExprNode* node)
358
358
{
359
- if (const auto listNode = nodeAs<InListBoolNode>(node))
359
+ auto factor = REDUCE_SELECTIVITY_FACTOR_OTHER;
360
+
361
+ if (const auto binaryNode = nodeAs<BinaryBoolNode>(node))
360
362
{
361
- const auto selectivity = REDUCE_SELECTIVITY_FACTOR_EQUALITY *
362
- listNode->list ->items .getCount ();
363
- return MIN (selectivity, MAXIMUM_SELECTIVITY);
363
+ if (binaryNode->blrOp == blr_and)
364
+ factor = getSelectivity (binaryNode->arg1 ) * getSelectivity (binaryNode->arg2 );
365
+ else if (binaryNode->blrOp == blr_or)
366
+ factor = getSelectivity (binaryNode->arg1 ) + getSelectivity (binaryNode->arg2 );
367
+ else
368
+ fb_assert (false );
364
369
}
365
-
366
- if (nodeIs<MissingBoolNode>(node))
367
- return REDUCE_SELECTIVITY_FACTOR_EQUALITY;
368
-
369
- if (const auto cmpNode = nodeAs<ComparativeBoolNode>(node))
370
+ else if (const auto listNode = nodeAs<InListBoolNode>(node))
371
+ {
372
+ factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY * listNode->list ->items .getCount ();
373
+ }
374
+ else if (nodeIs<MissingBoolNode>(node))
375
+ {
376
+ factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY;
377
+ }
378
+ else if (const auto cmpNode = nodeAs<ComparativeBoolNode>(node))
370
379
{
371
380
switch (cmpNode->blrOp )
372
381
{
373
382
case blr_eql:
374
383
case blr_equiv:
375
- return REDUCE_SELECTIVITY_FACTOR_EQUALITY;
384
+ factor = REDUCE_SELECTIVITY_FACTOR_EQUALITY;
385
+ break ;
376
386
377
387
case blr_gtr:
378
388
case blr_geq:
379
- return REDUCE_SELECTIVITY_FACTOR_GREATER;
389
+ factor = REDUCE_SELECTIVITY_FACTOR_GREATER;
390
+ break ;
380
391
381
392
case blr_lss:
382
393
case blr_leq:
383
- return REDUCE_SELECTIVITY_FACTOR_LESS;
394
+ factor = REDUCE_SELECTIVITY_FACTOR_LESS;
395
+ break ;
384
396
385
397
case blr_between:
386
- return REDUCE_SELECTIVITY_FACTOR_BETWEEN;
398
+ factor = REDUCE_SELECTIVITY_FACTOR_BETWEEN;
399
+ break ;
387
400
388
401
case blr_starting:
389
- return REDUCE_SELECTIVITY_FACTOR_STARTING;
402
+ factor = REDUCE_SELECTIVITY_FACTOR_STARTING;
403
+ break ;
390
404
391
405
default :
392
406
break ;
393
407
}
394
408
}
395
409
396
- return REDUCE_SELECTIVITY_FACTOR_OTHER;
410
+ // dimitr:
411
+ //
412
+ // Adjust to values similar to those used when the index selectivity is missing.
413
+ // The final value will be in the range [0.1 .. 0.5] that also matches the v3/v4 logic.
414
+ // This estimation is quite pessimistic but it seems to work better in practice,
415
+ // especially when multiple unmatchable booleans are used.
416
+
417
+ const auto adjustment = DEFAULT_SELECTIVITY / REDUCE_SELECTIVITY_FACTOR_EQUALITY;
418
+ const auto selectivity = factor * adjustment;
419
+
420
+ return MIN (selectivity, MAXIMUM_SELECTIVITY / 2 );
397
421
}
398
422
399
423
static void adjustSelectivity (double & selectivity, double factor, double cardinality)
400
424
{
401
- if (cardinality)
402
- {
403
- const auto minSelectivity = 1 / cardinality;
404
- const auto diffSelectivity = selectivity > minSelectivity ?
405
- selectivity - minSelectivity : 0 ;
406
- selectivity = minSelectivity + diffSelectivity * factor ;
407
- }
425
+ if (! cardinality)
426
+ cardinality = DEFAULT_CARDINALITY;
427
+
428
+ const auto minSelectivity = MAXIMUM_SELECTIVITY / cardinality;
429
+ const auto diffSelectivity = selectivity > minSelectivity ?
430
+ selectivity - minSelectivity : 0 ;
431
+ selectivity = minSelectivity + diffSelectivity * factor;
408
432
}
409
433
410
434
static RecordSource* compile (thread_db* tdbb, CompilerScratch* csb, RseNode* rse)
0 commit comments