Dela via


Prestandaräknare i ADO.NET

ADO.NET 2.0 introducerade utökat stöd för prestandaräknare som innehåller stöd för både System.Data.SqlClient och System.Data.OracleClient. Prestandaräknarna System.Data.SqlClient som är tillgängliga i tidigare versioner av ADO.NET har blivit inaktuella och ersatta med de nya prestandaräknarna som beskrivs i det här avsnittet. Du kan använda ADO.NET prestandaräknare för att övervaka status för ditt program och de anslutningsresurser som används. Prestandaräknare kan övervakas med hjälp av Windows Prestandaövervakare eller kan nås programmatiskt med hjälp av PerformanceCounter klassen i System.Diagnostics namnområdet.

Tillgängliga prestandaräknare

För närvarande finns det 14 olika prestandaräknare tillgängliga för System.Data.SqlClient och System.Data.OracleClient enligt beskrivningen i följande tabell. Observera att namnen för de enskilda räknarna inte är lokaliserade i regionala versioner av Microsoft .NET Framework.

Prestandaräknare beskrivning
HardConnectsPerSecond Antalet anslutningar per sekund som görs till en databasserver.
HardDisconnectsPerSecond Antalet frånkopplingar per sekund som görs till en databasserver.
NumberOfActiveConnectionPoolGroups Antalet unika anslutningspoolgrupper som är aktiva. Den här räknaren styrs av antalet unika niska veze som finns i AppDomain.
NumberOfActiveConnectionPools Det totala antalet anslutningspooler.
NumberOfActiveConnections Antalet aktiva anslutningar som används för närvarande. Obs! Den här prestandaräknaren är inte aktiverad som standard. Information om hur du aktiverar den här prestandaräknaren finns i Aktivera off-by-default-räknare.
NumberOfFreeConnections Antalet anslutningar som är tillgängliga för användning i anslutningspoolerna. Obs! Den här prestandaräknaren är inte aktiverad som standard. Information om hur du aktiverar den här prestandaräknaren finns i Aktivera off-by-default-räknare.
NumberOfInactiveConnectionPoolGroups Antalet unika anslutningspoolgrupper som har markerats för rensning. Den här räknaren styrs av antalet unika niska veze som finns i AppDomain.
NumberOfInactiveConnectionPools Antalet inaktiva anslutningspooler som inte har haft någon nyligen genomförd aktivitet och som väntar på att tas bort.
NumberOfNonPooledConnections Antalet aktiva anslutningar som inte är poolade.
NumberOfPooledConnections Antalet aktiva anslutningar som hanteras av infrastrukturen för anslutningspooler.
NumberOfReclaimedConnections Antalet anslutningar som har återtagits via skräpinsamling där Close programmet anropade eller Dispose inte anropades. Att inte uttryckligen stänga eller ta bort anslutningar skadar prestandan.
NumberOfStasisConnections Antalet anslutningar som väntar på att slutföra en åtgärd och som därför inte är tillgängliga för användning av ditt program.
SoftConnectsPerSecond Antalet aktiva anslutningar som hämtas från anslutningspoolen. Obs! Den här prestandaräknaren är inte aktiverad som standard. Information om hur du aktiverar den här prestandaräknaren finns i Aktivera off-by-default-räknare.
SoftDisconnectsPerSecond Antalet aktiva anslutningar som returneras till anslutningspoolen. Obs! Den här prestandaräknaren är inte aktiverad som standard. Information om hur du aktiverar den här prestandaräknaren finns i Aktivera off-by-default-räknare.

Anslutningspoolgrupper och anslutningspooler

När du använder Windows-autentisering (integrerad säkerhet) måste du övervaka både NumberOfActiveConnectionPoolGroups prestandaräknarna och NumberOfActiveConnectionPools . Orsaken är att anslutningspoolgrupper mappas till unika niska veze. När integrerad säkerhet används mappas anslutningspooler till niska veze och skapar dessutom separata pooler för enskilda Windows-identiteter. Om Till exempel Fred och Julie, var och en inom samma AppDomain, båda använder niska veze "Data Source=MySqlServer;Integrated Security=true", skapas en anslutningspoolgrupp för niska veze och ytterligare två pooler skapas, en för Fred och en för Julie. Om John och Martha använder en niska veze med en identisk SQL Server-inloggning "Data Source=MySqlServer;User Id=lowPrivUser;Password=[PLACEHOLDER]"skapas bara en enda pool för lowPrivUser-identiteten.

Viktigt!

Microsoft rekommenderar att du använder det säkraste tillgängliga autentiseringsflödet. Om du ansluter till Azure SQL är hanterade identiteter för Azure-resurser den rekommenderade autentiseringsmetoden.

Aktivera off-by-default-räknare

Prestandaräknarna NumberOfFreeConnections, NumberOfActiveConnections, SoftDisconnectsPerSecondoch SoftConnectsPerSecond är inaktiverade som standard. Lägg till följande information i programmets konfigurationsfil för att aktivera dem:

<system.diagnostics>
  <switches>
    <add name="ConnectionPoolPerformanceCounterDetail"
         value="4"/>
  </switches>
</system.diagnostics>

Hämtar värden för prestandaräknare

Följande konsolprogram visar hur du hämtar prestandaräknarens värden i ditt program. Anslutningar måste vara öppna och aktiva för att information ska returneras för alla ADO.NET prestandaräknare.

Kommentar

I det här exemplet används exempeldatabasen AdventureWorks som ingår i SQL Server. De niska veze som anges i exempelkoden förutsätter att databasen är installerad och tillgänglig på den lokala datorn med instansnamnet SqlExpress och att du har skapat SQL Server-inloggningar som matchar de som anges i niska veze. Du kan behöva aktivera SQL Server-inloggningar om servern har konfigurerats med standardsäkerhetsinställningarna som endast tillåter Windows-autentisering. Ändra niska veze efter behov för att passa din miljö.

Exempel

Option Explicit On
Option Strict On

Imports System.Data.SqlClient
Imports System.Diagnostics
Imports System.Runtime.InteropServices

Class Program

    Private PerfCounters(9) As PerformanceCounter
    Private connection As SqlConnection = New SqlConnection

    Public Shared Sub Main()
        Dim prog As Program = New Program
        ' Open a connection and create the performance counters.
        prog.connection.ConnectionString = _
           GetIntegratedSecurityConnectionString()
        prog.SetUpPerformanceCounters()
        Console.WriteLine("Available Performance Counters:")

        ' Create the connections and display the results.
        prog.CreateConnections()
        Console.WriteLine("Press Enter to finish.")
        Console.ReadLine()
    End Sub

    Private Sub CreateConnections()
        ' List the Performance counters.
        WritePerformanceCounters()

        ' Create 4 connections and display counter information.
        Dim connection1 As SqlConnection = New SqlConnection( _
           GetIntegratedSecurityConnectionString)
        connection1.Open()
        Console.WriteLine("Opened the 1st Connection:")
        WritePerformanceCounters()

        Dim connection2 As SqlConnection = New SqlConnection( _
           GetSqlConnectionStringDifferent)
        connection2.Open()
        Console.WriteLine("Opened the 2nd Connection:")
        WritePerformanceCounters()

        Console.WriteLine("Opened the 3rd Connection:")
        Dim connection3 As SqlConnection = New SqlConnection( _
           GetSqlConnectionString)
        connection3.Open()
        WritePerformanceCounters()

        Dim connection4 As SqlConnection = New SqlConnection( _
           GetSqlConnectionString)
        connection4.Open()
        Console.WriteLine("Opened the 4th Connection:")
        WritePerformanceCounters()

        connection1.Close()
        Console.WriteLine("Closed the 1st Connection:")
        WritePerformanceCounters()

        connection2.Close()
        Console.WriteLine("Closed the 2nd Connection:")
        WritePerformanceCounters()

        connection3.Close()
        Console.WriteLine("Closed the 3rd Connection:")
        WritePerformanceCounters()

        connection4.Close()
        Console.WriteLine("Closed the 4th Connection:")
        WritePerformanceCounters()
    End Sub

    Private Enum ADO_Net_Performance_Counters
        NumberOfActiveConnectionPools
        NumberOfReclaimedConnections
        HardConnectsPerSecond
        HardDisconnectsPerSecond
        NumberOfActiveConnectionPoolGroups
        NumberOfInactiveConnectionPoolGroups
        NumberOfInactiveConnectionPools
        NumberOfNonPooledConnections
        NumberOfPooledConnections
        NumberOfStasisConnections
        ' The following performance counters are more expensive to track.
        ' Enable ConnectionPoolPerformanceCounterDetail in your config file.
        '     SoftConnectsPerSecond
        '     SoftDisconnectsPerSecond
        '     NumberOfActiveConnections
        '     NumberOfFreeConnections
    End Enum

    Private Sub SetUpPerformanceCounters()
        connection.Close()
        Me.PerfCounters(9) = New PerformanceCounter()

        Dim instanceName As String = GetInstanceName()
        Dim apc As Type = GetType(ADO_Net_Performance_Counters)
        Dim i As Integer = 0
        Dim s As String = ""
        For Each s In [Enum].GetNames(apc)
            Me.PerfCounters(i) = New PerformanceCounter()
            Me.PerfCounters(i).CategoryName = ".NET Data Provider for SqlServer"
            Me.PerfCounters(i).CounterName = s
            Me.PerfCounters(i).InstanceName = instanceName
            i = (i + 1)
        Next
    End Sub

    Private Declare Function GetCurrentProcessId Lib "kernel32.dll" () As Integer

    Private Function GetInstanceName() As String
        'This works for Winforms apps.
        Dim instanceName As String = _
           System.Reflection.Assembly.GetEntryAssembly.GetName.Name

        ' Must replace special characters like (, ), #, /, \\
        Dim instanceName2 As String = _
           AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _
           .Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_")

        'For ASP.NET applications your instanceName will be your CurrentDomain's
        'FriendlyName. Replace the line above that sets the instanceName with this:
        'instanceName = AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _
        '    .Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_")

        Dim pid As String = GetCurrentProcessId.ToString
        instanceName = (instanceName + ("[" & (pid & "]")))
        Console.WriteLine("Instance Name: {0}", instanceName)
        Console.WriteLine("---------------------------")
        Return instanceName
    End Function

    Private Sub WritePerformanceCounters()
        Console.WriteLine("---------------------------")
        For Each p As PerformanceCounter In Me.PerfCounters
            Console.WriteLine("{0} = {1}", p.CounterName, p.NextValue)
        Next
        Console.WriteLine("---------------------------")
    End Sub
End Class
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    PerformanceCounter[] PerfCounters = new PerformanceCounter[10];
    SqlConnection connection = new SqlConnection();

    static void Main()
    {
        Program prog = new Program();
        // Open a connection and create the performance counters.
        prog.connection.ConnectionString =
           GetIntegratedSecurityConnectionString();
        prog.SetUpPerformanceCounters();
        Console.WriteLine("Available Performance Counters:");

        // Create the connections and display the results.
        prog.CreateConnections();
        Console.WriteLine("Press Enter to finish.");
        Console.ReadLine();
    }

    private void CreateConnections()
    {
        // List the Performance counters.
        WritePerformanceCounters();

        // Create 4 connections and display counter information.
        SqlConnection connection1 = new SqlConnection(
              GetIntegratedSecurityConnectionString());
        connection1.Open();
        Console.WriteLine("Opened the 1st Connection:");
        WritePerformanceCounters();

        SqlConnection connection2 = new SqlConnection(
              GetSqlConnectionStringDifferent());
        connection2.Open();
        Console.WriteLine("Opened the 2nd Connection:");
        WritePerformanceCounters();

        SqlConnection connection3 = new SqlConnection(
              GetSqlConnectionString());
        connection3.Open();
        Console.WriteLine("Opened the 3rd Connection:");
        WritePerformanceCounters();

        SqlConnection connection4 = new SqlConnection(
              GetSqlConnectionString());
        connection4.Open();
        Console.WriteLine("Opened the 4th Connection:");
        WritePerformanceCounters();

        connection1.Close();
        Console.WriteLine("Closed the 1st Connection:");
        WritePerformanceCounters();

        connection2.Close();
        Console.WriteLine("Closed the 2nd Connection:");
        WritePerformanceCounters();

        connection3.Close();
        Console.WriteLine("Closed the 3rd Connection:");
        WritePerformanceCounters();

        connection4.Close();
        Console.WriteLine("Closed the 4th Connection:");
        WritePerformanceCounters();
    }

    private enum ADO_Net_Performance_Counters
    {
        NumberOfActiveConnectionPools,
        NumberOfReclaimedConnections,
        HardConnectsPerSecond,
        HardDisconnectsPerSecond,
        NumberOfActiveConnectionPoolGroups,
        NumberOfInactiveConnectionPoolGroups,
        NumberOfInactiveConnectionPools,
        NumberOfNonPooledConnections,
        NumberOfPooledConnections,
        NumberOfStasisConnections
        // The following performance counters are more expensive to track.
        // Enable ConnectionPoolPerformanceCounterDetail in your config file.
        //     SoftConnectsPerSecond
        //     SoftDisconnectsPerSecond
        //     NumberOfActiveConnections
        //     NumberOfFreeConnections
    }

    private void SetUpPerformanceCounters()
    {
        connection.Close();
        this.PerfCounters = new PerformanceCounter[10];
        string instanceName = GetInstanceName();
        Type apc = typeof(ADO_Net_Performance_Counters);
        int i = 0;
        foreach (string s in Enum.GetNames(apc))
        {
            this.PerfCounters[i] = new PerformanceCounter();
            this.PerfCounters[i].CategoryName = ".NET Data Provider for SqlServer";
            this.PerfCounters[i].CounterName = s;
            this.PerfCounters[i].InstanceName = instanceName;
            i++;
        }
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern int GetCurrentProcessId();

    private string GetInstanceName()
    {
        //This works for Winforms apps.
        string instanceName =
            System.Reflection.Assembly.GetEntryAssembly().GetName().Name;

        // Must replace special characters like (, ), #, /, \\
        string instanceName2 =
            AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(', '[')
            .Replace(')', ']').Replace('#', '_').Replace('/', '_').Replace('\\', '_');

        // For ASP.NET applications your instanceName will be your CurrentDomain's
        // FriendlyName. Replace the line above that sets the instanceName with this:
        // instanceName = AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(','[')
        // .Replace(')',']').Replace('#','_').Replace('/','_').Replace('\\','_');

        string pid = GetCurrentProcessId().ToString();
        instanceName = instanceName + "[" + pid + "]";
        Console.WriteLine("Instance Name: {0}", instanceName);
        Console.WriteLine("---------------------------");
        return instanceName;
    }

    private void WritePerformanceCounters()
    {
        Console.WriteLine("---------------------------");
        foreach (PerformanceCounter p in this.PerfCounters)
        {
            Console.WriteLine("{0} = {1}", p.CounterName, p.NextValue());
        }
        Console.WriteLine("---------------------------");
    }
}

Se även