估计从 SQL 返回的数据集的大小

Estimate the size of a dataset returned from SQL

我们的系统似乎消耗了大量数据,它使用 Dapper 进行数据库查询,使用 Seq 进行日志记录。我想知道除了使用 SQL Profiler 之外,是否有一种方法可以将日志记录添加到 Dapper 以记录以 MB 为单位返回的数据集的大小 - 这样我们就可以标记大型数据集以供审查?

这个问题 has been asked a while ago 但我想知道现在是否有一种方法可以不用 wireshark 并且最好不用遍历 rows/cells?

不是真正完整的答案,但可能对您有所帮助。

sys.dm_exec_query_statssys.dm_exec_connections 可能会帮助您跟踪大型结果集。例如:

SELECT * FROM sys.dm_exec_query_stats 
CROSS APPLY sys.dm_exec_sql_text(sql_handle)

(单位为8k页)

这种方式为您提供了目前使用 wireshark 的目的(有点 :)

SELECT * FROM sys.dm_exec_connections
CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle)
ORDER BY num_writes DESC

https://msdn.microsoft.com/en-us/library/ms189741.aspx

https://msdn.microsoft.com/en-AU/library/ms181509.aspx

您可以估算一行所需的大小,将每个列类型的大小相加,然后乘以行数。如果您的查询中没有 TEXT / VARCHAR,它应该是准确的:

int rowSize = 0;
foreach(DataColumn dc in Dataset1.Tables[0].Columns) {
    rowSize += sizeof(dc.DataType);
}
int dataSize = rowSize * Dataset1.Tables[0].Rows.Count;

如果您需要更准确的数字,请使用 Marshal.SizeOf:

总结每个值的大小
int dataSize = 0;
foreach(DataRow dr in Dataset1.Tables[0].Rows) 
{
    int rowSize = 0;
    for (int i = 0; i < Dataset1.Tables[0].Columns.Count; i++)
    {
        rowSize += System.Runtime.InteropServices.Marshal.SizeOf(dr[i]);
    }
    dataSize += rowSize;
}

如果不考虑高精度,提高性能的想法:

  1. 计算一个样本的大小。比方说,不是遍历所有行,而是每 100 行中选择 1 行,然后最后将结果乘以 100。
  2. 使用 [Marshal.SizeOf]((https://msdn.microsoft.com/en-us/library/y3ybkfb3.aspx) 计算每个 DataRow 的大小 dr 而不是遍历它的所有值。它会给你一个更大的数字,因为DataRow 对象具有其他属性,但您可以通过减去空 DataRow 的大小来调整这些属性。
  3. 事先知道单行的平均大小,通过它的列数,然后乘以行数。

我会为基础存储库 class 中的连接配置 Provider Statistics for SQL Server。您可以添加一个配置设置来打开它,并轻松地将此信息保存到日志文件或任何您想要的地方。

来自 MSDN 的示例代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

namespace CS_Stats_Console_GetValue
{
  class Program
  {
    static void Main(string[] args)
    {
      string connectionString = GetConnectionString();

      using (SqlConnection awConnection = 
        new SqlConnection(connectionString))
      {
        // StatisticsEnabled is False by default.
        // It must be set to True to start the 
        // statistic collection process.
        awConnection.StatisticsEnabled = true;

        string productSQL = "SELECT * FROM Production.Product";
        SqlDataAdapter productAdapter = 
          new SqlDataAdapter(productSQL, awConnection);

        DataSet awDataSet = new DataSet();

        awConnection.Open();

        productAdapter.Fill(awDataSet, "ProductTable");
        // Retrieve the current statistics as
        // a collection of values at this point
        // and time.
        IDictionary currentStatistics =
          awConnection.RetrieveStatistics();

        Console.WriteLine("Total Counters: " +
          currentStatistics.Count.ToString());
        Console.WriteLine();

        // Retrieve a few individual values
        // related to the previous command.
        long bytesReceived =
            (long) currentStatistics["BytesReceived"];
        long bytesSent =
            (long) currentStatistics["BytesSent"];
        long selectCount =
            (long) currentStatistics["SelectCount"];
        long selectRows =
            (long) currentStatistics["SelectRows"];

        Console.WriteLine("BytesReceived: " +
            bytesReceived.ToString());
        Console.WriteLine("BytesSent: " +
            bytesSent.ToString());
        Console.WriteLine("SelectCount: " +
            selectCount.ToString());
        Console.WriteLine("SelectRows: " +
            selectRows.ToString());

        Console.WriteLine();
        Console.WriteLine("Press any key to continue");
        Console.ReadLine();
      }

    }
    private static string GetConnectionString()
    {
      // To avoid storing the connection string in your code,
      // you can retrive it from a configuration file.
      return "Data Source=localhost;Integrated Security=SSPI;" + 
        "Initial Catalog=AdventureWorks";
    }
  }
}

我们仅通过 capping/limiting 查询大小就解决了这个限制。这使我们不必担心大小和进行双重查询。我们使用的 PR 您也可以使用 https://github.com/DapperLib/Dapper/pull/1758/files