/// <summary> /// Returns a list of conditon groups and an associated list of supporting indexes to satisify each group (nested conditions). /// </summary> /// <param name="transaction"></param> /// <param name="schemaMeta"></param> /// <param name="conditions"></param> /// <returns></returns> public List <IndexSelections> SelectIndexes(Transaction transaction, PersistSchema schemaMeta, Conditions conditions) { List <IndexSelections> indexSelections = new List <IndexSelections>(); IndexSelections indexSelection = new IndexSelections(conditions); SelectIndexes(transaction, schemaMeta, conditions.Root, ref indexSelection); indexSelections.Add(indexSelection); if (conditions.Children != null && conditions.Children.Count > 0) { foreach (var childConditions in conditions.Children) { var childIndexSelections = SelectIndexes(transaction, schemaMeta, childConditions); if (childIndexSelections != null && childIndexSelections.Count > 0) { indexSelections.AddRange(childIndexSelections); } } } return(indexSelections); }
private void SelectIndexes(Transaction transaction, PersistSchema schemaMeta, List <Condition> conditions, ref IndexSelections indexSelection) { try { var indexCatalog = GetIndexCatalog(transaction, schemaMeta, LockOperation.Read); List <PotentialIndex> potentialIndexs = new List <PotentialIndex>(); var indexConditions = new IndexConditions(conditions); //Loop though each index in the schema and create a list of all indexes which could potentially be used to match the conditions. foreach (var indexMeta in indexCatalog.Collection) { var indexHandledCondition = new List <IndexHandledCondition>(); for (int i = 0; i < indexMeta.Attributes.Count; i++) { var indexConditonMatches = indexConditions.FindAll(o => o.Key == indexMeta.Attributes[i].Name.ToLower() && o.Handled == false); if (indexConditonMatches.Count > 0) { foreach (var indexConditonMatche in indexConditonMatches) { indexHandledCondition.Add(new IndexHandledCondition(indexConditonMatche, i)); } } else { break; } } if (indexHandledCondition.Count > 0) { potentialIndexs.Add(new PotentialIndex(indexMeta, indexHandledCondition)); } } //Group the indexes by their first attribute. var distinctFirstAttributes = potentialIndexs.Select(o => o.Index.Attributes[0].Name).Distinct(); foreach (var distinctFirstAttribute in distinctFirstAttributes) { //Find all idexes with the same first attribute: var indexGroup = potentialIndexs.Where(o => o.FirstAttributeName == distinctFirstAttribute); //For the group of indexes, find the one index that handles the most keys but also has the fewest atributes. var firstIndexInGroup = (from o in indexGroup select o) .OrderByDescending(s => s.IndexHandledConditions.Count) .ThenBy(t => t.Index.Attributes.Count).FirstOrDefault(); foreach (var indexHandledCondition in firstIndexInGroup.IndexHandledConditions) { //Mark the keys which are handled by this index as "handled". var handledKeys = (from o in indexConditions where o.Id == indexHandledCondition.Id select o).ToList(); foreach (var handledKey in handledKeys) { handledKey.Handled = true; } } indexSelection.Add(new IndexSelection(firstIndexInGroup.Index, firstIndexInGroup.IndexHandledConditions)); } indexSelection.UnhandledKeys.AddRange((from o in indexConditions where o.Handled == false select o.Key).ToList()); } catch (Exception ex) { core.Log.Write(String.Format("Failed to select indexes for process {0}.", transaction.ProcessId), ex); throw; } }