Adding top operations to execution plan (#1563)

* Adding more rules for prop

* adding top operations to ep

* Reverting changes made to display cost

* Fixing comments

* Removing whitespace

* Fixing data size property
This commit is contained in:
Aasim Khan
2022-07-05 20:18:24 -07:00
committed by GitHub
parent 671310880b
commit e64e31e487
7 changed files with 439 additions and 8 deletions

View File

@@ -79,6 +79,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts
/// Add badge icon to nodes like warnings and parallelism
/// </summary>
public List<Badge> Badges { get; set; }
/// <summary>
/// Top operations table data for the node
/// </summary>
public List<TopOperationsDataItem> TopOperationsData { get; set; }
}
public class ExecutionPlanGraphPropertyBase
@@ -206,4 +210,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts
Boolean = 2,
Nested = 3
}
public class TopOperationsDataItem
{
public string ColumnName { get; set; }
public PropertyValueDataType DataType { get; set; }
public object DisplayValue { get; set; }
}
}

View File

@@ -34,7 +34,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
}
public static ExecutionPlanNode ConvertShowPlanTreeToExecutionPlanTree(Node currentNode)
{
{
return new ExecutionPlanNode
{
ID = currentNode.ID,
@@ -49,7 +49,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
Edges = currentNode.Edges.Select(x => ConvertShowPlanEdgeToExecutionPlanEdge(x)).ToList(),
Badges = GenerateNodeOverlay(currentNode),
Name = currentNode.DisplayName,
ElapsedTimeInMs = currentNode.ElapsedTimeInMs
ElapsedTimeInMs = currentNode.ElapsedTimeInMs,
TopOperationsData = ParseTopOperationsData(currentNode)
};
}
@@ -163,6 +164,173 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
return propsList;
}
public static List<TopOperationsDataItem> ParseTopOperationsData(Node currentNode)
{
List<TopOperationsDataItem> result = new List<TopOperationsDataItem>();
result.Add(new TopOperationsDataItem
{
ColumnName = SR.Operation,
DataType = PropertyValueDataType.String,
DisplayValue = currentNode.Operation.DisplayName
});
if (currentNode["Object"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.Object,
DataType = PropertyValueDataType.String,
DisplayValue = ((ExpandableObjectWrapper)currentNode["Object"]).DisplayName
});
}
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedCost,
DataType = PropertyValueDataType.Number,
DisplayValue = Math.Round(currentNode.Cost, 1)
});
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedSubtree,
DataType = PropertyValueDataType.Number,
DisplayValue = Math.Round(currentNode.SubtreeCost, 1)
});
if (currentNode["ActualRows"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.ActualRows,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["ActualRows"]
});
}
if (currentNode["AvgRowSize"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedAverageRowSize,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["AvgRowSize"]
});
}
if (currentNode["ActualExecutions"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.ActualExecutions,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["ActualExecutions"]
});
}
if (currentNode["EstimateExecutions"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedExecutions,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["EstimateExecutions"]
});
}
if (currentNode["EstimateCPU"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedCpu,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["EstimateCPU"]
});
}
if (currentNode["EstimateIO"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedIO,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["EstimateIO"]
});
}
if (currentNode["Parallel"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.Parallel,
DataType = PropertyValueDataType.Boolean,
DisplayValue = currentNode["Parallel"]
});
}
if (currentNode["Ordered"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.Ordered,
DataType = PropertyValueDataType.Boolean,
DisplayValue = currentNode["Ordered"]
});
}
if (currentNode["ActualRewinds"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.ActualRewinds,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["ActualRewinds"]
});
}
if (currentNode["EstimateRewinds"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedRewinds,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["EstimateRewinds"]
});
}
if (currentNode["ActualRebinds"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.ActualRebinds,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["ActualRebinds"]
});
}
if (currentNode["EstimateRebinds"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.EstimatedRebinds,
DataType = PropertyValueDataType.Number,
DisplayValue = currentNode["EstimateRebinds"]
});
}
if (currentNode["Partitioned"] != null)
{
result.Add(new TopOperationsDataItem
{
ColumnName = SR.Partitioned,
DataType = PropertyValueDataType.Boolean,
DisplayValue = currentNode["Partitioned"]
});
}
return result;
}
private static List<ExecutionPlanRecommendation> ParseRecommendations(ShowPlanGraph g, string fileName)
{
return g.Description.MissingIndices.Select(mi => new ExecutionPlanRecommendation

View File

@@ -576,11 +576,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
return true;
}
/// <summary>
/// Gets lines of text displayed under the icon.
/// </summary>
/// <returns>Array of strings.</returns>
/// <summary>
/// Gets lines of text displayed under the icon.
/// </summary>
@@ -595,7 +590,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
if (!this.HasPDWCost || cost > 0)
{
if(roundCostForSmallGraph && this.graph != null && this.graph.NodeStmtMap.Count < 20){
if (roundCostForSmallGraph && this.graph != null && this.graph.NodeStmtMap.Count < 20)
{
cost = Math.Round(cost);
}
string costText = SR.CostFormat(cost.ToString("0.##"));

View File

@@ -8485,6 +8485,102 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
public static string Operation
{
get
{
return Keys.GetString(Keys.Operation);
}
}
public static string Object
{
get
{
return Keys.GetString(Keys.Object);
}
}
public static string EstimatedCost
{
get
{
return Keys.GetString(Keys.EstimatedCost);
}
}
public static string EstimatedSubtree
{
get
{
return Keys.GetString(Keys.EstimatedSubtree);
}
}
public static string ActualRows
{
get
{
return Keys.GetString(Keys.ActualRows);
}
}
public static string EstimatedRows
{
get
{
return Keys.GetString(Keys.EstimatedRows);
}
}
public static string ActualExecutions
{
get
{
return Keys.GetString(Keys.ActualExecutions);
}
}
public static string EstimatedExecutions
{
get
{
return Keys.GetString(Keys.EstimatedExecutions);
}
}
public static string EstimatedCpu
{
get
{
return Keys.GetString(Keys.EstimatedCpu);
}
}
public static string EstimatedIO
{
get
{
return Keys.GetString(Keys.EstimatedIO);
}
}
public static string EstimatedAverageRowSize
{
get
{
return Keys.GetString(Keys.EstimatedAverageRowSize);
}
}
public static string ActualDataSize
{
get
{
return Keys.GetString(Keys.ActualDataSize);
}
}
public static string TableEditPathNotProvidedException
{
get
@@ -12950,6 +13046,42 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string ParallelismOverlayTooltip = "ParallelismOverlayTooltip";
public const string Operation = "Operation";
public const string Object = "Object";
public const string EstimatedCost = "EstimatedCost";
public const string EstimatedSubtree = "EstimatedSubtree";
public const string ActualRows = "ActualRows";
public const string EstimatedRows = "EstimatedRows";
public const string ActualExecutions = "ActualExecutions";
public const string EstimatedExecutions = "EstimatedExecutions";
public const string EstimatedCpu = "EstimatedCpu";
public const string EstimatedIO = "EstimatedIO";
public const string EstimatedAverageRowSize = "EstimatedAverageRowSize";
public const string ActualDataSize = "ActualDataSize";
public const string TableNotInitializedException = "TableNotInitializedException";

View File

@@ -4644,6 +4644,54 @@ The Query Processor estimates that implementing the following index could improv
<value>Parallel Execution</value>
<comment>tooltip text for node parallelism overlay</comment>
</data>
<data name="Operation" xml:space="preserve">
<value>Operation</value>
<comment></comment>
</data>
<data name="Object" xml:space="preserve">
<value>Object</value>
<comment></comment>
</data>
<data name="EstimatedCost" xml:space="preserve">
<value>Estimated Cost %</value>
<comment></comment>
</data>
<data name="EstimatedSubtree" xml:space="preserve">
<value>Estimated Subtree Cost %</value>
<comment></comment>
</data>
<data name="ActualRows" xml:space="preserve">
<value>Actual Rows</value>
<comment></comment>
</data>
<data name="EstimatedRows" xml:space="preserve">
<value>Estimated Rows</value>
<comment></comment>
</data>
<data name="ActualExecutions" xml:space="preserve">
<value>Actual Executions</value>
<comment></comment>
</data>
<data name="EstimatedExecutions" xml:space="preserve">
<value>Estimated Executions</value>
<comment></comment>
</data>
<data name="EstimatedCpu" xml:space="preserve">
<value>Estimated CPU Cost</value>
<comment></comment>
</data>
<data name="EstimatedIO" xml:space="preserve">
<value>Estimated IO Cost</value>
<comment></comment>
</data>
<data name="EstimatedAverageRowSize" xml:space="preserve">
<value>Estimated Average Row Size</value>
<comment></comment>
</data>
<data name="ActualDataSize" xml:space="preserve">
<value>Actual Data Size</value>
<comment></comment>
</data>
<data name="TableNotInitializedException" xml:space="preserve">
<value>Initialization is not properly done for table with id &apos;{0}&apos;</value>
<comment>.

View File

@@ -2234,6 +2234,22 @@ WarningOverlayTooltip = Warnings
;tooltip text for node parallelism overlay
ParallelismOverlayTooltip = Parallel Execution
#
# Top operation column Names
#
Operation = Operation
Object = Object
EstimatedCost = Estimated Cost %
EstimatedSubtree = Estimated Subtree Cost %
ActualRows = Actual Rows
EstimatedRows = Estimated Rows
ActualExecutions = Actual Executions
EstimatedExecutions = Estimated Executions
EstimatedCpu = Estimated CPU Cost
EstimatedIO = Estimated IO Cost
EstimatedAverageRowSize = Estimated Average Row Size
ActualDataSize = Actual Data Size
############################################################################
# Table Designer

View File

@@ -6194,6 +6194,66 @@ The Query Processor estimates that implementing the following index could improv
<target state="new">There are multiple table definitions in the script, only the first table can be edited in the designer.</target>
<note></note>
</trans-unit>
<trans-unit id="Operation">
<source>Operation</source>
<target state="new">Operation</target>
<note></note>
</trans-unit>
<trans-unit id="Object">
<source>Object</source>
<target state="new">Object</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedCost">
<source>Estimated Cost %</source>
<target state="new">Estimated Cost %</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedSubtree">
<source>Estimated Subtree Cost %</source>
<target state="new">Estimated Subtree Cost %</target>
<note></note>
</trans-unit>
<trans-unit id="ActualRows">
<source>Actual Rows</source>
<target state="new">Actual Rows</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedRows">
<source>Estimated Rows</source>
<target state="new">Estimated Rows</target>
<note></note>
</trans-unit>
<trans-unit id="ActualExecutions">
<source>Actual Executions</source>
<target state="new">Actual Executions</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedExecutions">
<source>Estimated Executions</source>
<target state="new">Estimated Executions</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedCpu">
<source>Estimated CPU Cost</source>
<target state="new">Estimated CPU Cost</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedIO">
<source>Estimated IO Cost</source>
<target state="new">Estimated IO Cost</target>
<note></note>
</trans-unit>
<trans-unit id="ActualDataSize">
<source>Actual Data Size</source>
<target state="new">Actual Data Size</target>
<note></note>
</trans-unit>
<trans-unit id="EstimatedAverageRowSize">
<source>Estimated Average Row Size</source>
<target state="new">Estimated Average Row Size</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>