0

我在清理数据的 SSIS 脚本组件中使用 VB.Net 语言。(视觉工作室 2010)

这是代码:

Public Sub Main()
    Dim pk As New Package
    Dim file As New System.IO.StreamReader(Dts.Variables("User::str_SourcePath").Value.ToString())
    Dim data As String
    data = file.ReadToEnd()
    data = data.Replace("'", "")
    data = data.Replace(Chr(0), "")
    data = data.Replace(Chr(1), "")
    file.Close()
    Dim writer As New System.IO.StreamWriter(Dts.Variables("User::str_SourcePath").Value.ToString(), False)
    writer.Write(data)
    writer.Flush()
    writer.Close()

    Dts.TaskResult = ScriptResults.Success
End Sub

即使有非常大的文件,当我在本地运行此脚本任务时,它也会成功运行,但部署的包仅在处理大文件(即超过 100 MB)时在服务器上失败。(SQL Server 2012)

4

3 回答 3

0

我为解决方案写了一篇博客。 http://sqldeveloper9999.wordpress.com/2013/10/03/script-component-working-locally-but-not-on-sql-server/

于 2013-10-03T23:47:20.923 回答
0

尽管您没有错误消息,但我假设您正在抛出内存不足错误。

您有哪些解决方案?

在问题上投入更多的硬件。

确保您在 64 位模式下执行包(这排除了使用 JET/Excel 驱动程序)。如果您的 RAM 仍然不足,请在 ETL 运行之前添加更多内存或执行一些操作以释放内存。

修复你的代码

现在,您的代码正在将文件的全部内容读入内存以开始进行替换。

修复 A

字符串是不可变的,这意味着您拥有的每个字符串都位于内存中。我的理解是,data由于您执行的操作,您没有 1 个副本,而是有 4 个不同的副本。如果您改用 StringBuilder 类,那么它应该更适合您的记忆。

修复 B

分块读取数据。是的,你需要负责更多的编码,但由于你不能在问题上投入更多的硬件,你必须停止做坏事。A for each loop 读取和写入擦洗的行就足够了。

于 2013-09-25T18:17:27.990 回答
0

您应该一次读取和写入 1 行,这通常更快,并且几乎不使用内存。

Public Sub Main()
    Dim pk As New Package
    Dim file As New System.IO.StreamReader(Dts.Variables("User::str_SourcePath").Value.ToString())
    'Must save it to a temp file since you cannot update the file you are reading.
    Dim sTempFile As String = "c:\temp\MyTemp.txt"
    If IO.File.Exists(sTempFile) Then IO.File.Delete(sTempFile)
    Dim writer As New System.IO.StreamWriter(sTempFile, False)
    Dim data As String
    While Not file.EndOfStream
        data = file.ReadLine
        data = data.Replace("'", "")
        data = data.Replace(Chr(0), "")
        data = data.Replace(Chr(1), "")

        writer.WriteLine(data)
    End While
    file.Close()
    writer.Flush()
    writer.Close()
    'Rename (move) your temp file to the original name
    If IO.File.Exists(Dts.Variables("User::str_SourcePath").Value.ToString()) Then IO.File.Delete(Dts.Variables("User::str_SourcePath").Value.ToString())
    IO.File.Move(sTempFile, Dts.Variables("User::str_SourcePath").Value.ToString())

    Dts.TaskResult = ScriptResults.Success
End Sub
于 2013-09-25T18:56:55.613 回答