Tempo e Eficiência SQL

0 respostas
dmandrak

E ae pessoal!

Mais uma vez venho eu recorrer a vocês!

É o 'sisguinte', na minha aplicação em vb.net eu pego de um banco de dados sql local e escrevo em um outro local (reformatando os campos) e em um outro remoto.

O motivo da escrita no remoto e no local (reformatado) é diferente.

No bd local original eu tenho duas colunas booleanas - EnviadoPI e EnviadoLocalMES - que me dizem se o dado já foi enviado alguma vez para algum dos outros bancos.

O problema é:

1 - Quando o dado nasce, ele não é necessariamente enviado.
2 - na hora de enviar:
2.1- Primeiro vai para o PI e atualiza sua coluna EnviadoPI (banco remoto)
2.2 - Depois vai pro LocalMES e atualiza sua coluna EnviadoLocalMES
- caso dê erro no envio ele loga o erro e aborta as rotinas, ou seja, deixa de enviar o restante.

Com isso, não é necessariamente verdade que eu tenha que enviar sempre para o LocalMES e o PI junto.

Porém, da maneira como criei meu programa, ele lê o banco de dados original e faz:
comandoSelectSQLDadosDesenfornamento.CommandText = _
                    "SELECT " & _
                        "DateAndTime as DataHora, TagIndex as id, Val as Valor, EnviadoPI, EnviadoLocalMES " & _
                    "FROM " & _
                        "FloatTable " & _
                    "WHERE " & _
                        "(DateAndTime IS NOT NULL) AND " & _
                        "(TagIndex IS NOT NULL) AND " & _
                        "(Val IS NOT NULL) AND" & _
                        "(((EnviadoPI != 'False') OR (EnviadoPI IS NULL)) OR" & _
                        "((EnviadoLocalMES != 'False') OR (EnviadoLocalMES IS NULL)))" & _
                        "ORDER BY " & _
                        "DateAndTime"

Ou seja, ele pega todo mundo que não tenho sido enviado para o PI OU que não tenha sido enviado para o LocalMES e armazena num dataset.

Na hora de escrever nos bancos, obviamente ele escreve um de cada vez e atualiza a respectiva coluna no dataset.

If dsDadosBat4e5.Tables("DadosDesenfornamento").Rows.Count > 0 Then

            'Loop para gravar os dados de Desenfornamento no PI.
            For Each linhaAuxiliarDesenfornamento In dsDadosBat4e5.Tables("DadosDesenfornamento").Rows

                If (IsDBNull(linhaAuxiliarDesenfornamento.Item("EnviadoPI")) Or linhaAuxiliarDesenfornamento.Item("EnviadoPI").Equals(False)) Then

                    'Faz o tratamento dos ids, para ser escrito no PI.
                    'O Tag Bat4e5_RtPM_Desenforn_Maquina identifica a Desenfornadora (3, 4 ou 5)
                    Select Case linhaAuxiliarDesenfornamento.Item("id")
                        Case 0
                            Tag1 = "Bat4e5_RtPM_Desenforn_AmperagemMax"
                        Case 1
                            Tag1 = "Bat4e5_RtPM_Desenforn_AmperagemMedia"
                        Case 2
                            Tag1 = "Bat4e5_RtPM_Desenforn_Numforno"
                        Case 3
                            Tag1 = "Bat4e5_RtPM_Desenforn_Maquina"
                        Case 4
                            Tag1 = "Bat4e5_RtPM_Desenforn_TempoCoqueif"
                            'DataHora Real, Programada, Temperatura1, 2 e 3 ainda não implementadas
                        Case 5
                            Tag1 = "Bat4e5_RtPM_Desenforn_DataHora_Programada"
                        Case 6
                            Tag1 = "Bat4e5_RtPM_Desenforn_DataHora_Real"
                        Case 7
                            Tag1 = "Bat4e5_RtPM_Desenforn_Temperatura1"
                        Case 8
                            Tag1 = "Bat4e5_RtPM_Desenforn_Temperatura2"
                        Case 9
                            Tag1 = "Bat4e5_RtPM_Desenforn_Temperatura3"
                    End Select

                    comandoInsertPIDadosBat4e5.CommandType = CommandType.Text
                    comandoInsertPIDadosBat4e5.CommandText = _
                    "INSERT INTO " & _
                        "picomp2 " & _
                        "(tag, time, value) " & _
                    "VALUES " & _
                        "('" & Tag1 & "', " & _
                        "'" & Format(CDate(linhaAuxiliarDesenfornamento.Item("DataHora")), "dd/MM/yyyy HH:mm:ss") & "', " & _
                       "'" & Trim(linhaAuxiliarDesenfornamento.Item("Valor")).ToString & "')"

                    comandoInsertPIDadosBat4e5.Connection = conexaoPIDadosBat4e5
                    adaptadorPIDadosBat4e5.InsertCommand = comandoInsertPIDadosBat4e5

                    Try
                        conexaoPIDadosBat4e5.Open()
                        adaptadorPIDadosBat4e5.InsertCommand.ExecuteReader()
                    Catch ex As Exception
                        MessageBox.Show(ex.ToString)
                        arqLog.EscreverLinha(Format(Now, "yyyy-MM-dd HH:mm:ss") & "   " & "Erro: Falha na gravação do tag dados de Desenfornamento " & linhaAuxiliarDesenfornamento.Item("id") & "   -   " & ex.Message)
                        erroGravacaoPI = True
                        Exit For
                    Finally
                        If conexaoPIDadosBat4e5.State <> ConnectionState.Closed Then
                            conexaoPIDadosBat4e5.Close()
                        End If
                    End Try
                End If
 'Atualizando o flag de 'EnviadoPI' na tabela de Desenfornamento do RS View do banco local.
                If Not erroGravacaoPI Then

                    comandoUpdateSQLDadosDesenfornamento.CommandType = CommandType.Text
                    comandoUpdateSQLDadosDesenfornamento.CommandText = _
                    "UPDATE " & _
                        "FloatTable " & _
                    "SET " & _
                        "EnviadoPI = 'True' " & _
                    "WHERE " & _
                        "(DateAndTime = " & "CONVERT(DATETIME, '" & Format(CDate(linhaAuxiliarDesenfornamento.Item("DataHora")), "yyyy-MM-dd HH:mm:ss") & "', 102)" & ") AND " & _
                        "(Val = '" & linhaAuxiliarDesenfornamento.Item("Valor") & "'" & ")"


                    comandoUpdateSQLDadosDesenfornamento.Connection = SqlConexaoDadosDesenfornamento
                    adaptadorSQLDadosDesenfornamento.UpdateCommand = comandoUpdateSQLDadosDesenfornamento

                    Try
                        SqlConexaoDadosDesenfornamento.Open()
                        adaptadorSQLDadosDesenfornamento.UpdateCommand.ExecuteReader()
                    Catch ex As Exception
                        MessageBox.Show(ex.ToString)
                        arqLog.EscreverLinha(Format(Now, "yyyy-MM-dd HH:mm:ss") & "   " & "Erro: Falha na atualização do flag 'EnviadoPI' na tabela de Desenfornamento do banco de dados do RS View!" & "   -   " & ex.Message)
                        erroGravacaoPI = True
                        Exit For
                    Finally
                        If SqlConexaoDadosDesenfornamento.State <> ConnectionState.Closed Then
                            SqlConexaoDadosDesenfornamento.Close()
                        End If
                    End Try
                End If

Para cada linha no dataset ele faz isso.

O problema é que na hora de fazer a mesma coisa para o MES eu vou ter que abrir uma conexão nova com o banco sql.

A minha pergunta é:

O certo seria atualizar o banco de dados 1 vez só no final da rotina (pensando em eficiência) porém como eu falei, se der um erro, perco as atualizações que deveriam ter sido feitas até aquele momento e corro o risco de re-enviar dados desnecessariamente.

Logo eu perco eficiência praticamente dobrando meus acessos ao banco de dados.

Alguém tem alguma idéia mágica para me ajudar?

A máquina que isso vai rodar é boa porém ela tem duzentas outras aplicações mais imoportantes rodando 'full-time' enquanto essa rotina é lançada de tempos em tempos quando ocorre um evento pré-determinado, logo, não quero destruir o processamento dela com enormes loops duplicados e triplicados à toa...

Vocês pelo menos entenderam a idéia? :roll: Eu imagino que ela esteja meio confusa, vou tentar pensar numa maneira de explicar melhor e posto aqui.

Abração!

edit 1:

Já pensei um pouco.

Nesse caso, essas coisas seriam pesadas, as conexões, leituras, escritas no banco de dados, dataset, o tratamento dos dados (formatação de strings por exemplo)?

Eu nunca fiz nada 'concreto' (se podemos dizer) em sql e vb.net para ter essas informações.

Esse que é o meu dilema, abusar da segurança lendo e escrevendo separadamente, abrindo mão assim da eficiência, ou tentar otimizar algumas coisas.

Lembrando que pelo que eu vi no histórico desse processo, o evento de envio acontece umas 10x por dia e são normalmente uns 40-50 dados por envio.

Ah, outra coisa!

São 3 conjuntos de tabelas originais (ou 3 BD diferentes) que passam pelas mesmas rotinas ao mesmo tempo, mesmo que apenas um tenha sido atualizado com dados novos.

Criado 24 de setembro de 2008
Respostas 0
Participantes 1