private void EstimateRows(MatchGraph graph)
{
var declareParameter = "";
if (_variables != null)
{
declareParameter = _variables.Aggregate(declareParameter,
(current, parameter) =>
current +
("DECLARE " + parameter.VariableName.Value + " " +
TsqlFragmentToString.DataType(parameter.DataType) + "\r\n"));
}
var estimator = new TableSizeEstimator(Tx);
bool first = true;
// Constructs a union-all query in which each sub-query is a selection of
// a node table alias plus predicates that can be associated with it.
// This query is sent to the SQL DB to get the estimated cardinality of
// each node table alias.
var estimateQuerySb = new StringBuilder(1024);
foreach (var subGraph in graph.ConnectedSubGraphs)
{
foreach (var node in subGraph.Nodes)
{
if (first)
first = false;
else
estimateQuerySb.Append("\r\nUNION ALL\r\n");
var currentNode = node.Value;
estimateQuerySb.AppendFormat("SELECT GlobalNodeId FROM {0} AS [{1}]",
currentNode.NodeTableObjectName,
currentNode.NodeAlias);
if (currentNode.Predicates != null && currentNode.Predicates.Count > 0)
{
estimateQuerySb.AppendFormat("\r\nWHERE {0}", currentNode.Predicates[0]);
for (int i = 1; i < currentNode.Predicates.Count; i++)
{
var predicate = currentNode.Predicates[i];
estimateQuerySb.AppendFormat(" AND {0}", predicate);
}
}
}
}
string nodeEstimationQuery = string.Format("{0}\r\n {1}\r\n", declareParameter,
estimateQuerySb);
// A list of estimated cardinalities
var estimateRows = estimator.GetUnionQueryTableEstimatedRows(nodeEstimationQuery);
int j = 0;
foreach (var subGraph in graph.ConnectedSubGraphs)
{
// Update Row Estimation for nodes
foreach (var node in subGraph.Nodes)
{
var currentNode = node.Value;
var tableSchema = currentNode.NodeTableObjectName.SchemaIdentifier.Value;
var tableName = currentNode.NodeTableObjectName.BaseIdentifier.Value;
var tableTuple = WNamedTableReference.SchemaNameToTuple(currentNode.NodeTableObjectName);
if (_graphMetaData.NodeViewMapping.ContainsKey(tableTuple))
{
var nodeSet = _graphMetaData.NodeViewMapping[tableTuple];
int n = nodeSet.Count;
double nodeViewEstRows = 0.0;
currentNode.TableRowCount = nodeSet.Aggregate(0,
(cur, next) => cur + estimator.GetTableRowCount(tableSchema, next));
bool bug = false;
while (n > 0)
{
n--;
if (j > estimateRows.Count - 1)
{
bug = true;
break;
}
nodeViewEstRows += estimateRows[j];
j++;
}
currentNode.EstimatedRows = bug ? currentNode.TableRowCount : nodeViewEstRows;
}
else
{
currentNode.TableRowCount = estimator.GetTableRowCount(tableSchema, tableName);
if (j > estimateRows.Count - 1)
currentNode.EstimatedRows = currentNode.TableRowCount;
else
currentNode.EstimatedRows = estimateRows[j];
j++;
}
}
}
}