mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Additional Execution Plan Node Properties for Highlighting Expensive Operators (#1683)
* Adds cost metric information to the node. * Gets the elapsed CPU time by the node operation * Renames DTO property to row metrics * Removes unused class * Simplify checks for row property values * Cleans up model for node cost metrics * Removes duplicate code * Switching to primitive type empty string * Code review changes
This commit is contained in:
@@ -63,7 +63,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts
|
||||
/// </summary>
|
||||
public double RelativeCost { get; set; }
|
||||
/// <summary>
|
||||
/// Time take by the node operation in milliseconds
|
||||
/// Time taken by the node operation in milliseconds
|
||||
/// </summary>
|
||||
public long? ElapsedTimeInMs { get; set; }
|
||||
/// <summary>
|
||||
@@ -92,6 +92,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts
|
||||
/// Top operations table data for the node
|
||||
/// </summary>
|
||||
public List<TopOperationsDataItem> TopOperationsData { get; set; }
|
||||
/// <summary>
|
||||
/// The cost metrics for the node.
|
||||
/// </summary>
|
||||
public List<CostMetric> CostMetrics { get; set; }
|
||||
}
|
||||
|
||||
public class CostMetric
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the cost metric
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The value for the cost metric
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ExecutionPlanGraphPropertyBase
|
||||
|
||||
@@ -33,8 +33,40 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private static void ParseCostMetricProperty(List<CostMetric> costMetrics, string name, PropertyValue? property)
|
||||
{
|
||||
if (property != null)
|
||||
{
|
||||
var costMetric = new CostMetric()
|
||||
{
|
||||
Name = name,
|
||||
Value = ExecutionPlanGraphUtils.GetPropertyDisplayValue(property)
|
||||
};
|
||||
|
||||
costMetrics.Add(costMetric);
|
||||
}
|
||||
}
|
||||
|
||||
public static ExecutionPlanNode ConvertShowPlanTreeToExecutionPlanTree(Node currentNode)
|
||||
{
|
||||
var costMetrics = new List<CostMetric>();
|
||||
|
||||
var elapsedCpuTimeInMs = currentNode.ElapsedCpuTimeInMs;
|
||||
if (elapsedCpuTimeInMs.HasValue)
|
||||
{
|
||||
var costMetric = new CostMetric()
|
||||
{
|
||||
Name = "ElapsedCpuTime",
|
||||
Value = $"{elapsedCpuTimeInMs.Value}"
|
||||
};
|
||||
costMetrics.Add(costMetric);
|
||||
}
|
||||
|
||||
ExecutionPlanGraphUtils.ParseCostMetricProperty(costMetrics, "EstimateRowsAllExecs", currentNode.Properties["EstimateRowsAllExecs"] as PropertyValue);
|
||||
ExecutionPlanGraphUtils.ParseCostMetricProperty(costMetrics, "EstimatedRowsRead", currentNode.Properties["EstimatedRowsRead"] as PropertyValue);
|
||||
ExecutionPlanGraphUtils.ParseCostMetricProperty(costMetrics, "ActualRows", currentNode.Properties["ActualRows"] as PropertyValue);
|
||||
ExecutionPlanGraphUtils.ParseCostMetricProperty(costMetrics, "ActualRowsRead", currentNode.Properties["ActualRowsRead"] as PropertyValue);
|
||||
|
||||
return new ExecutionPlanNode
|
||||
{
|
||||
ID = currentNode.ID,
|
||||
@@ -52,7 +84,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
||||
Badges = GenerateNodeOverlay(currentNode),
|
||||
Name = currentNode.DisplayName,
|
||||
ElapsedTimeInMs = currentNode.ElapsedTimeInMs,
|
||||
TopOperationsData = ParseTopOperationsData(currentNode)
|
||||
TopOperationsData = ParseTopOperationsData(currentNode),
|
||||
CostMetrics = costMetrics
|
||||
};
|
||||
}
|
||||
|
||||
@@ -134,6 +167,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
||||
propertyDataType = PropertyValueDataType.String;
|
||||
break;
|
||||
}
|
||||
|
||||
propsList.Add(new ExecutionPlanGraphProperty()
|
||||
{
|
||||
Name = prop.DisplayName,
|
||||
@@ -412,8 +446,13 @@ GO
|
||||
";
|
||||
}
|
||||
|
||||
private static string GetPropertyDisplayValue(PropertyValue property)
|
||||
private static string GetPropertyDisplayValue(PropertyValue? property)
|
||||
{
|
||||
if (property == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Get the property value.
|
||||
@@ -421,7 +460,7 @@ GO
|
||||
|
||||
if (propertyValue == null)
|
||||
{
|
||||
return String.Empty;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Convert the property value to the text.
|
||||
@@ -430,7 +469,7 @@ GO
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Write(TraceEventType.Error, e.ToString());
|
||||
return String.Empty;
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -501,6 +501,26 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
|
||||
}
|
||||
}
|
||||
|
||||
public long? ElapsedCpuTimeInMs
|
||||
{
|
||||
get
|
||||
{
|
||||
long? time = null;
|
||||
var actualStatsWrapper = this["ActualTimeStatistics"] as ExpandableObjectWrapper;
|
||||
if (actualStatsWrapper != null)
|
||||
{
|
||||
var counters = actualStatsWrapper["ActualCPUms"] as RunTimeCounters;
|
||||
if (counters != null)
|
||||
{
|
||||
var elapsedTime = counters.MaxCounter;
|
||||
long ticks = (long)elapsedTime * TimeSpan.TicksPerMillisecond;
|
||||
time = new DateTime(ticks).Millisecond;
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ENU name for Logical Operator
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user