想要在每个数据库上运行查询,如何计算C#和SQL Server中的性能差异

本文关键字:SQL 计算 Server 性能 数据库 运行 何计算 查询 | 更新日期: 2023-09-27 18:21:31

我正在开发sql server监控产品,我有一个数据库查询,它将获取有关sql server中所有数据库的所有表详细信息的数据。

对此,我有两种选择。

  1. select name from [master].sys.sysdatabases的形式从代码中激发数据库查询首先获取所有数据库的数据库名称,然后我将在每个数据库上启动主查询使用"USE <fetched DB name>;"+"mainQuery";

    请检查以下代码是否相同。

    public DataTable GetResultsOfAllDB(string query)
    {
        SqlConnection con = new SqlConnection(_ConnectionString);
        string locleQuery = "select name from [master].sys.sysdatabases";
        DataTable dtResult = new DataTable("Result");
        SqlCommand cmdData = new SqlCommand(locleQuery, con);
        cmdData.CommandTimeout = 0;
        SqlDataAdapter adapter = new SqlDataAdapter(cmdData);
        DataTable dtDataBases = new DataTable("DataBase");
        adapter.Fill(dtDataBases);
        foreach (DataRow drDB in dtDataBases.Rows)
        {
            if (dtResult.Rows.Count >= 15000)
                break;
            locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query;
            cmdData = new SqlCommand(locleQuery, con);
            adapter = new SqlDataAdapter(cmdData);
            DataTable dtTemp = new DataTable();
            adapter.Fill(dtTemp);
            dtResult.Merge(dtTemp);
        }
        return dtResult;
    }
    
  2. 我将使用系统存储过程,即EXEC sp_MSforeachdb,提取的数据将存储在从临时表中选择的表数据类型中;删除表临时表。检查相同的以下查询

    Declare @TableDetail table ( field1 varchar(500), field2 int, field3 varchar(500), field4 varchar(500), field5 decimal(18,2), field6 decimal(18,2) ) INSERT @TableDetail EXEC sp_MSforeachdb 'USE [?]; QYERY/COMMAND FOR ALL DATABASE' Select field1,field2 ,field3 ,field4 ,field5,field6 FROM @TableDetail

注意:在第二个选项中,查询需要时间,因为如果数据库的数量和表的数量很大,那么这将等待所有数据库完成。

现在我的问题是,从以上两个选项中,哪一个是好的选项,为什么?或其任何其他解决方案。

提前谢谢。

想要在每个数据库上运行查询,如何计算C#和SQL Server中的性能差异

一个关键区别是第二个选项块,直到一切完成。所有的工作都是在sql服务器端完成的。这就带来了无法在运行时向用户应用反馈的问题,而且它可能会超时,无法适应网络突发事件。这个选项可以用作纯sql脚本(有些sql管理员喜欢这样),其中第一个需要程序。

在第一个示例中,客户端正在执行更精细的迭代任务,您可以在其中向用户提供反馈。你也可以在面对网络故障时重试,而无需重做所有工作。在第一个示例中,您还可以使用SqlConnectionBuild而不是use连接。

如果性能是一个问题,您还可以通过一些锁定适配器来并行化第一个问题。填充

两者都很糟糕-它们都是串行的。

使用第一个,去掉荒谬的对象(DataSet),同时使用TASKS并行化X数据库。X通过尝试服务器可以处理多少负载来确定。

完成。

如果查询足够简单,您可以尝试生成单个脚本,而不是在每个DB中逐个执行查询:

select 'DB1' as DB, Field1, Field2, ...
from [DB1]..[TableOrViewName]
union all
select 'DB2' as DB, Field1, Field2, ...
from [DB2]..[TableOrViewName]
union all
...

一切看起来都很好。我只想为IDisposable对象添加Using语句

public DataTable GetResultsOfAllDB(string query)
        {
            using (SqlConnection con = new SqlConnection(_ConnectionString))
            {
                string locleQuery = "select name from [master].sys.sysdatabases";
                DataTable dtResult = new DataTable("Result");
                using (SqlCommand cmdData = new SqlCommand(locleQuery, con))
                {
                    cmdData.CommandTimeout = 0;
                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmdData))
                    {
                        using (DataTable dtDataBases = new DataTable("DataBase"))
                        {
                            adapter.Fill(dtDataBases);
                            foreach (DataRow drDB in dtDataBases.Rows)
                            {
                                if (dtResult.Rows.Count >= 15000)
                                    break;
                                locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query;
                                cmdData = new SqlCommand(locleQuery, con);
                                adapter = new SqlDataAdapter(cmdData);
                                using (DataTable dtTemp = new DataTable())
                                {
                                    adapter.Fill(dtTemp);
                                    dtResult.Merge(dtTemp);
                                }
                            }
                            return dtResult;
                        }
                    }
                }
            }
        }