Udostępnij za pośrednictwem


Liczniki wydajności w programie SqlClient

Dotyczy: .NET Framework

Pobieranie ADO.NET

Możesz użyć liczników wydajności do monitorowania stanu aplikacji i zasobów połączenia, które wykorzystuje. Liczniki wydajności można monitorować przy użyciu Monitora wydajności systemu Windows lub można uzyskać do tego dostęp programowo, korzystając z klasy PerformanceCounter w przestrzeni nazw System.Diagnostics.

Ważna

Podejście PerformanceCounteroparte na metodzie opisane w tym artykule wymaga programu .NET Framework i działa tylko w systemie Windows. Klasa System.Diagnostics.PerformanceCounter nie jest dostępna na platformach .NET Core, .NET 5 lub nowszych niż Windows. W przypadku monitorowania międzyplatformowego w nowoczesnych aplikacjach .NET zamiast tego użyj liczników zdarzeń w programie SqlClient .

Dostępne liczniki wydajności

Obecnie dostępnych jest 14 różnych liczników wydajności dla Microsoft.Data.SqlClient, jak opisano w poniższej tabeli.

Licznik wydajności Description
HardConnectsPerSecond Liczba połączeń na sekundę, które są wykonywane na serwerze bazy danych.
HardDisconnectsPerSecond Liczba rozłączeń na sekundę, które są wykonywane na serwerze bazy danych.
NumberOfActiveConnectionPoolGroups Liczba unikatowych grup puli połączeń, które są aktywne. Ten licznik jest kontrolowany przez liczbę unikalnych ciągów połączeń znalezionych w domenie aplikacji.
NumberOfActiveConnectionPools Łączna liczba pul połączeń.
NumberOfActiveConnections Liczba aktywnych połączeń, które są obecnie używane. Uwaga: Ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników wyłączonych domyślnie.
NumberOfFreeConnections Liczba połączeń dostępnych do użycia w pulach połączeń. Uwaga: Ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników wyłączonych domyślnie.
NumberOfInactiveConnectionPoolGroups Liczba unikalnych grup puli połączeń oznaczonych do usunięcia. Ten licznik jest kontrolowany przez liczbę unikatowych ciągów połączeń znalezionych w domenie aplikacji.
NumberOfInactiveConnectionPools Liczba nieaktywnych pul połączeń, które nie miały ostatnio żadnej aktywności i które oczekują na likwidację.
NumberOfNonPooledConnections Liczba aktywnych połączeń, które nie są w puli.
NumberOfPooledConnections Liczba aktywnych połączeń zarządzanych przez infrastrukturę buforowania połączeń.
NumberOfReclaimedConnections Liczba połączeń, które zostały odzyskane poprzez zbieranie śmieci, gdzie Close lub Dispose nie zostały wywołane przez aplikację. Uwaga Nie zamykaj jawnie ani nie usuwaj połączeń, co szkodzi wydajności.
NumberOfStasisConnections Liczba połączeń oczekujących na ukończenie działania i dlatego są niedostępne do użytku przez twoją aplikację.
SoftConnectsPerSecond Liczba aktywnych połączeń pobieranych z puli połączeń. Uwaga: Ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników wyłączonych domyślnie.
SoftDisconnectsPerSecond Liczba aktywnych połączeń zwracanych do puli połączeń. Uwaga: Ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników wyłączonych domyślnie.

Włączanie liczników domyślnie wyłączonych

Liczniki NumberOfFreeConnectionswydajności , NumberOfActiveConnections, SoftDisconnectsPerSecondi SoftConnectsPerSecond są domyślnie wyłączone. Dodaj następujące informacje do pliku konfiguracji aplikacji, aby je włączyć:

<system.diagnostics>  
  <switches>  
    <add name="ConnectionPoolPerformanceCounterDetail" value="4"/>  
    <!-- A value of 4 corresponds to System.Diagnostics.TraceLevel.Verbose -->
  </switches>  
</system.diagnostics>  

Pobieranie wartości licznika wydajności

Poniższa aplikacja konsolowa pokazuje, jak pobrać wartości liczników wydajności w aplikacji. Połączenia muszą być otwarte i aktywne, aby informacje zostały zwrócone dla wszystkich liczników wydajności dostarczanych przez dostawcę danych Microsoft SqlClient dla SQL Server.

Uwaga / Notatka

W tym przykładzie użyto przykładowej bazy danych AdventureWorks. Parametry połączenia podane w przykładowym kodzie zakładają, że baza danych jest zainstalowana i dostępna na komputerze lokalnym oraz że utworzono identyfikatory logowania zgodne z parametrami połączenia. Może być konieczne włączenie loginów SQL Server, jeśli serwer jest skonfigurowany przy użyciu domyślnych ustawień zabezpieczeń, które zezwalają tylko na uwierzytelnianie Windows. Zmodyfikuj parametry połączenia zgodnie z potrzebami w twoim środowisku.

Example

using System;
using Microsoft.Data.SqlClient;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace SqlClient_PerformanceCounter
{
    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("---------------------------");
        }

        private static string GetIntegratedSecurityConnectionString()
        {
            // To avoid storing the connection string in your code,  
            // you can retrieve it from a configuration file.  
            return @"Data Source=.;Integrated Security=True;" +
              "Initial Catalog=AdventureWorks";
        }
        private static string GetSqlConnectionString()
        {
            // To avoid storing the connection string in your code,  
            // you can retrieve it from a configuration file.  
            return @"Data Source=.;User Id=<myUserID>;Password=<myPassword>;" +
              "Initial Catalog=AdventureWorks";
        }

        private static string GetSqlConnectionStringDifferent()
        {
            // To avoid storing the connection string in your code,  
            // you can retrieve it from a configuration file.  
            return @"Initial Catalog=AdventureWorks;Data Source=.;" +
              "User Id=<myUserID>;Password=<myPassword>;";
        }
    }
}