mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-25 09:35:37 -05:00
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:
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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.##"));
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
|
||||
@@ -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 '{0}'</value>
|
||||
<comment>.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user