/// <summary> /// Assigns a proxy predicate to a multi-attributed expression. /// </summary> private static IProxyPredicate GetMultiAttributePredicate(ComparisonPredicate expression, ICollection <IIndex> indices, IQueryStore queryStore) { var candidatesList = new OrderedList <int, IIndex>(); foreach (var index in indices) { List <string> indexAttributes = new List <string>(); indexAttributes.Add(index.Attributes.Name); if (ContainsRange(indexAttributes, expression.AttributeNames)) { candidatesList.Add(index.KeyCount, index); } } if (candidatesList.Count > 0) { var predicate = new FilterPredicate(expression, candidatesList.FirstValues[0]); predicate.AddChildPredicate(new AllPredicate(candidatesList.FirstValues[0])); return(new ProxyPredicate(predicate, expression)); } return(new ProxyPredicate(new StorePredicate(expression, queryStore), expression)); }
/// <summary> /// Tries to assign compound indexes to expressions if applicable... /// </summary> private static List <ProxyAndPredicate> AssignCompoundIndices(ProxyAndPredicate set, IEnumerable <IIndex> indexes, IQueryStore queryStore) { var attribExprList = new OrderedList <string, ComparisonPredicate>(); var proxyPredicates = new List <ProxyAndPredicate>(); //For every expression in the set ready for assignment. foreach (var expresson in set.TreePredicates) { var expression = (ComparisonPredicate)expresson; if (expression.IsBinaryExpression) { continue; } attribExprList.Add(expression.AttributeNames[0], expression); } //Each compound index will create a new state of the expression. foreach (var index in indexes) { int matchedNumber = 0; var matchedAttribs = new List <string>(); //If keys (attributes list) does not contain the first prefix of the index //Then the index is not usable. if (attribExprList.ContainsKey(index.Attributes.Name)) { matchedAttribs.Add(index.Attributes.Name); matchedNumber += attribExprList[index.Attributes.Name].Count; } //if matched attributes are < 2 no need of compound assignment. if (matchedAttribs.Count < 2) { continue; } //Assign each of them an index and get them to the predicate, and get the one with the lowest cost. ComparisonPredicate cheapestExpression = attribExprList[matchedAttribs[0]][0]; IPredicate cheapestPredicate = cheapestExpression.AssignIndexPredicate(index, queryStore); for (int i = 1; i < attribExprList[matchedAttribs[0]].Count; i++) { ComparisonPredicate tempExpression = attribExprList[matchedAttribs[0]][i]; IPredicate tempPredicate = tempExpression.AssignIndexPredicate(index, queryStore); if (tempPredicate.Statistics[Statistic.ExpectedIO] < cheapestPredicate.Statistics[Statistic.ExpectedIO]) { cheapestExpression = tempExpression; cheapestPredicate = tempPredicate; } } //For filteration and adding rest of expressions to the index. ITreePredicate assingedExpression = null; if (!matchedNumber.Equals(2)) { AndTreePredicate assingedAnd = new AndTreePredicate(); foreach (var attribute in matchedAttribs) { foreach (var expression in attribExprList[attribute]) { if (expression != cheapestExpression) { assingedAnd.Add(expression); } } } assingedExpression = assingedAnd; } else { foreach (var expression in attribExprList[matchedAttribs[1]]) { assingedExpression = expression; } } FilterPredicate filterPredicate = new FilterPredicate(assingedExpression, index); filterPredicate.AddChildPredicate(cheapestPredicate); ProxyAndPredicate proxyAnd = (ProxyAndPredicate)set.Clone(); //Removing assigned expressions. foreach (var attribute in matchedAttribs) { foreach (var expression in attribExprList[attribute]) { proxyAnd.TreePredicates.Remove(expression); } } proxyAnd.AddChildPredicate(new ProxyPredicate(filterPredicate, null)); proxyPredicates.Add(proxyAnd); } foreach (var proxyAnd in proxyPredicates) { //Recursive call for each ProxyAndPredicate. if (proxyAnd.TreePredicates.Count > 1) { var values = AssignCompoundIndices(proxyAnd, indexes, queryStore); foreach (var value in values) { proxyPredicates.Add(value); } } } return(proxyPredicates); }