开发者社区 问答 正文

识别在编写SQL时需要改进VBA代码的区域

我正在寻找优化以下模块的方法。

我将经常需要用我在excel工作表/工作簿中收到的带有大型数据集的数据库来更新数据库。我已经制作了一个模块,可以将工作表导入到指定的数据库中。在这里使用stringbuilder类-

https://codereview.stackexchange.com/questions/196076/bringing-the-system-text-stringbuilder-up-to-lightning-speed-in-the-vba

据我测试,它适用于非常大的数据集并处理我遇到的所有异常(只要数字列中没有字符串),但我更担心性能。立即写入,它以大约650行/秒的速度写入sql服务器。还有其他机会以这种/提高速度转储内存吗?之所以必须这样做,是因为数据集越大,导入速度越低。我不确定这是否是服务器。

Main函数,遍历该行,然后迭代到下一个,构建格式化的插入sql语句。

Public Sub buildQuery()
        Dim sb As StringBuilder
        Set sb = New StringBuilder
        Dim queryText As String
        Application.ScreenUpdating = False
        lr = Cells(Rows.Count, 4).End(xlUp).row
        lc = Cells(1, Columns.Count).End(xlToLeft).column
        Dim MyTimer As Date
        MyTimer = Now
        Debug.Print MyTimer

    For i = 2 To lr

    Application.StatusBar = "Progress: " & i & " of " & lr & " : " & format(i / lr, "0%")

        If (i Mod 1000) = 0 Then
            sb.Append buildRow(currentCell, i, n, lc)
            queryText = intoStatement() + sb.ToString
            queryText = Left(queryText, Len(queryText) - 1)
            query (queryText)
            Set sb = Nothing
            queryText = Nothing
            Set sb = New StringBuilder
            i = i + 1
            End If

        sb.Append buildRow(currentCell, i, n, lc)
        sb.Append vbNewLine

    Next i

    queryText = intoStatement() + sb.ToString
    queryText = Left(queryText, Len(queryText) - 3)
    query (queryText)

MyTimer = Now
Debug.Print MyTimer
Application.ScreenUpdating = True
Application.StatusBar = False
End
End Sub

在工作表中导入了一些极低的值,导致我不得不处理服务器端的类型错误,所以我做到了这一点。它只是将负数四舍五入到小数点后十位。

Function smallNo(no As Variant)

If IsNumeric(no) Then
     If no < 0 Then
     smallNo = Round(no, 10)
     Else
     smallNo = no
     End If

End Function
这将生成并返回按SQL要求格式化的单行

Function buildRow(currentCell As Variant, i As Variant, n As Variant, lc As Variant) As String

Dim sb As StringBuilder
Set sb = New StringBuilder

      For n = 1 To lc
        currentCell = smallNo(Cells(i, n))

        Select Case True
            Case IsError(currentCell), IsEmpty(currentCell)
                If n = 1 Then
                sb.Append ("(NULL,")
                ElseIf n = lc Then
                sb.Append "NULL),"
                Else
                sb.Append "NULL,"
                End If
            Case Else
               cellString = Replace(CStr(currentCell), ("'"), "")
                If n = 1 Then
                    sb.Append "('" & cellString & "',"
                ElseIf n = lc Then
                    sb.Append "'" & cellString & "'), "
                Else
                sb.Append Chr(39) & cellString & "',"
                End If
        End Select
        Next n
        buildRow = sb.ToString
        Set sb = Nothing
End Function

从标头构建插入***值。假定标题与数据库表中的列名相同。理想情况下,电子表格中的标题列将是您导入之前唯一需要进行的编辑。

Public Function intoStatement() As String
With ActiveSheet
 lc = .Cells(1, .Columns.Count).End(xlToLeft).column
    Dim headerCells As Variant
    headerCells = .Range(.Cells(1, 1), .Cells(1, lc))
End With

Dim headers As String
headers = Join(Application.Transpose(Application.Transpose(headerCells)), ",")

intoStatement = "INSERT INTO " & _
"[tempdb].[dbo].testDB3 (" & headers & ") Values "

End Function

在这里我们打开到sql server的连接并执行生成的查询。执行此操作后,将转储stringbuilder对象queryText

Function query(sqlStr As String)

Dim connection As New ADODB.connection
Dim strSQL As New ADODB.Command
Dim connString As String

connection.Open "DRIVER={SQL Server};SERVER=DESKTOP;" & _
       "trusted_connection=yes;dsn=tw;DATABASE=tempdb"

strSQL.ActiveConnection = connection
strSQL.CommandText = sqlStr
strSQL.CommandType = adCmdText

strSQL.Execute

connection.Close


End Function

展开
收起
心有灵_夕 2019-12-22 13:48:37 935 分享 版权
阿里云 AI 助理回答

优化Excel数据导入到SQL Server的过程,特别是在处理大型数据集时,确实需要一些策略来提高性能。以下是一些建议,结合使用阿里云产品和服务,可以帮助你提升数据导入速度和效率:

  1. 批量插入而非单行插入: 目前你的方法是逐行构建SQL语句并执行,这会带来大量的数据库交互开销。改为批量构建INSERT语句或直接使用SQL Server的BULK INSERT命令可以显著提高效率。你可以累积一定数量的记录后一次性提交到数据库,减少数据库操作次数。

  2. 使用ADO(ActiveX Data Objects)连接: ADO提供了一种更高效的方式来与数据库交互,特别是当你需要进行大量数据操作时。利用Recordset对象的Open方法配合合适的游标类型(如adOpenStaticadOpenForwardOnly),以及AddNewUpdateBatch方法来进行批量数据插入。

  3. 考虑使用阿里云DataWorks: 阿里云DataWorks是一个大数据开发和运维平台,它支持从各种数据源(包括Excel文件)抽取数据,并通过其强大的数据集成能力将数据加载到云数据库中。这样不仅可以避免编写复杂的VBA代码,还可以利用其内置的高性能数据同步功能,实现快速、稳定的数据迁移。

  4. MaxCompute(原ODPS)作为中间层: 如果你的最终目标是进行大数据分析,可以考虑先将Excel数据导入到MaxCompute中。MaxCompute提供了高并发、大吞吐量的数据导入能力,且支持多种数据格式。之后,再根据需要将数据进一步处理或迁移到其他数据库系统。

  5. 优化网络和数据库配置: 确保数据库服务器的网络连接良好,数据库参数(如缓冲池大小、日志文件设置等)根据数据导入任务进行了适当调整。如果使用的是阿里云RDS,可以通过监控和调优建议来优化数据库性能。

  6. 并行处理: 如果可能,尝试将数据分割成多个部分,并在不同的线程或进程中并行处理这些部分,最后汇总结果。但请注意,这可能需要更复杂的编程逻辑,并确保数据库能够处理并发写入。

  7. 直接使用阿里云DMS(Data Management Service)或Data Transmission Service: 这些服务提供了图形界面或API接口,帮助用户更加便捷地进行数据导入导出操作,尤其是当涉及到不同数据源之间的数据迁移时。

综上所述,结合技术手段和阿里云的产品服务,可以从多个维度优化你的数据导入流程,达到更高的效率和性能。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答