0

我有一个必须多次执行 sql 脚本的方法。这些脚本用于在数据库上创建表、视图、存储过程和函数。我想出了这段代码,它适用于 100 个文件。

foreach (var folder in ActivityConstant.SourceFolders)
{
    var destination = context.GetValue(this.DestinationPath) + folder;

    // TODO: Execute all sql folders instead of each sql file.
    // this is cmd command for %f in (*.sql) do sqlcmd /S <servername> /d <dbname> /E /i "%f"

    foreach (var file in Directory.GetFiles(destination))
    {
        var begin = DateTime.Now;
        context.TrackBuildWarning(string.Format("Start exec sql file at {0}.", 
                                                DateTime.Now));

        Process process = new Process();
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.FileName = "sqlcmd.exe";
        process.StartInfo.Arguments = string.Format("-S {0} -d {1} -i {2} -U {3} -P {4}", 
                                                    sqlServerName, 
                                                    databaseName, 
                                                    file, 
                                                    sqlUserName, 
                                                    sqlPassword);
        process.StartInfo.WorkingDirectory = @"C:\";
        process.Start();
        //process.WaitForExit();

        context.TrackBuildWarning(
           string.Format(
                "Finished exec sql file at {0} total time {1} milliseconds.", 
                DateTime.Now, 
                DateTime.Now.Subtract(begin).TotalMilliseconds));
    }
}

现在,我正在继续下一步。我正在使用我们的数据库对其进行测试,该数据库包含大约 600 个文件(表、视图、存储过程和函数),看起来当前代码无法处理这样的大量查询。

据我所知,运行大约 100 个文件需要 3 到 5 分钟。在我写这个问题的时候,这 600 个文件已经用了 40 分钟。

我想知道如何改进我的代码。如果最好使用不同的方式来实现目标,我也欢迎任何建议。

4

4 回答 4

2

您同时启动 600 个进程,这对性能不利,它们可能占用大量 RAM,可能会发生交换?

它还会在您的 SQL 服务器上产生大量负载,也可能是那里的内存问题。

尝试按顺序运行您的查询,或者一次至少只运行几个。

编辑
作为旁注,您应该考虑使用SqlCommand而不是启动外部进程。

于 2012-10-03T08:57:32.850 回答
0

我怀疑提高性能的最有用的方法是将实际 SQL 命令的执行转移到应用程序中。

这避免了

  • 创建许多进程(600 个,并行?!)
  • 重复连接(每个进程至少一个)
  • 次优锁争用(由于不确定的执行顺序)

我会考虑将脚本存储为资源,然后在 SqlConnection 上执行。

在适用时考虑事务管理。处理此问题的最简单方法是仍然 为每个“脚本”打开一个新连接。只要您每次使用相同的连接字符串执行此操作,框架就会自动将连接池化。

于 2012-10-03T08:58:09.950 回答
0

如果每组文件只有一个数据库 - 您不应该登录每个文件/查询。

于 2012-10-03T08:56:47.660 回答
0

您可以在执行之前尝试合并文件:

        using (var merged = File.OpenWrite("merged.sql"))
        {
            foreach (var file in Directory.GetFiles(destination))
            {
                var data = File.ReadAllBytes(file);
                merged.Write(data, 0, data.Length);
            }
        }
        //continue with "merged.sql" as source file for the sqlcmd

此外,对于这项任务,有多种现有工具,谷歌搜索“数据库部署工具”或类似的工具。

于 2012-10-03T09:01:35.093 回答