double ParameterizedFilter::EvaluateConditionNonJoinWeight(Descriptor &d, bool for_or) { // Interpretation of weight: // an approximation of logarithm of answer size // (in case of for_or: an approximation of (full_table - answer) size) // 0 -> time is very short (constant). // high weight -> schedule this query to be executed later double eval = 0.0; _uint64 no_distinct, no_distinct2; _uint64 answer_size; if(d.IsTrue() || d.IsFalse()) eval = 0; // constant time else if(d.IsType_AttrValOrAttrValVal()) { // typical condition: attr=val if(!d.encoded) { return log(1 + double(d.attr.vc->NoTuples())) + 5; // +5 as a penalty for complex expression } SingleColumn* col = static_cast<SingleColumn*>(d.attr.vc); answer_size = col->ApproxAnswerSize(d); if(for_or) answer_size = d.attr.vc->NoTuples() - answer_size; _int64 no_in_values = 1; if(d.op == O_IN || d.op == O_NOT_IN) { MultiValColumn* iscol = static_cast<MultiValColumn*>(d.val1.vc); no_in_values = iscol->NoValues(NULL); } eval = log(1 + double(answer_size)); // approximate size of the result if(no_in_values > 1) eval += log(double(no_in_values)) * 0.5; // INs are potentially slower (many comparisons needed) if(col->Type().IsString() && !col->Type().IsLookup()) eval += 0.5; // strings are slower if(col->Type().IsFloat()) eval += 0.1; // floats are slower if(d.op == O_LIKE || d.op == O_NOT_LIKE) eval += 0.2; // these operators need more work } else if(d.IsType_AttrAttr()) { // attr=attr on the same table _uint64 no_obj = d.attr.vc->NoTuples(); // changed to uint64 to prevent negative logarithm for NULL_VALUE_64 if(!d.encoded) return log(1 + double(2 * no_obj)) + 5; // +5 as a penalty for complex expression else if(d.op == O_EQ) { no_distinct = d.attr.vc->GetApproxDistVals(false); if(no_distinct == 0) no_distinct = 1; no_distinct2 = d.val1.vc->GetApproxDistVals(false); if(no_distinct2 == 0) no_distinct2 = 1; if(no_distinct2 > no_distinct) no_distinct = no_distinct2; // find the attribute with smaller abstract classes if(for_or) eval = log(1 + (no_obj - double(no_obj) / no_distinct)); else eval = log(1 + double(no_obj) / no_distinct); // size of the smaller abstract class } else { eval = log(1 + double(no_obj) / 2); // other operators filter potentially a half of objects } eval += 1; // add to compensate opening two packs } else if(d.IsType_OrTree() && !d.IsType_Join()) { eval = d.tree->root->EvaluateConditionWeight(this, for_or); } else { // expressions and other types, incl. joins (to be calculated separately) if(d.IsType_IBExpression()) return log(1 + double(d.attr.vc->NoTuples())) + 2; // +2 as a penalty for IB complex expression eval = 99999; } return eval; }