mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-03 09:35:39 -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>
|
/// </summary>
|
||||||
public double RelativeCost { get; set; }
|
public double RelativeCost { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time take by the node operation in milliseconds
|
/// Time taken by the node operation in milliseconds
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? ElapsedTimeInMs { get; set; }
|
public long? ElapsedTimeInMs { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -92,6 +92,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts
|
|||||||
/// Top operations table data for the node
|
/// Top operations table data for the node
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<TopOperationsDataItem> TopOperationsData { get; set; }
|
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
|
public class ExecutionPlanGraphPropertyBase
|
||||||
|
|||||||
@@ -33,8 +33,40 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
|||||||
}).ToList();
|
}).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)
|
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
|
return new ExecutionPlanNode
|
||||||
{
|
{
|
||||||
ID = currentNode.ID,
|
ID = currentNode.ID,
|
||||||
@@ -52,7 +84,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
|||||||
Badges = GenerateNodeOverlay(currentNode),
|
Badges = GenerateNodeOverlay(currentNode),
|
||||||
Name = currentNode.DisplayName,
|
Name = currentNode.DisplayName,
|
||||||
ElapsedTimeInMs = currentNode.ElapsedTimeInMs,
|
ElapsedTimeInMs = currentNode.ElapsedTimeInMs,
|
||||||
TopOperationsData = ParseTopOperationsData(currentNode)
|
TopOperationsData = ParseTopOperationsData(currentNode),
|
||||||
|
CostMetrics = costMetrics
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +167,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan
|
|||||||
propertyDataType = PropertyValueDataType.String;
|
propertyDataType = PropertyValueDataType.String;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
propsList.Add(new ExecutionPlanGraphProperty()
|
propsList.Add(new ExecutionPlanGraphProperty()
|
||||||
{
|
{
|
||||||
Name = prop.DisplayName,
|
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
|
try
|
||||||
{
|
{
|
||||||
// Get the property value.
|
// Get the property value.
|
||||||
@@ -421,7 +460,7 @@ GO
|
|||||||
|
|
||||||
if (propertyValue == null)
|
if (propertyValue == null)
|
||||||
{
|
{
|
||||||
return String.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the property value to the text.
|
// Convert the property value to the text.
|
||||||
@@ -430,7 +469,7 @@ GO
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Write(TraceEventType.Error, e.ToString());
|
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>
|
/// <summary>
|
||||||
/// ENU name for Logical Operator
|
/// ENU name for Logical Operator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user