MELHORIA DO CODIGO

AMELORP 10/05/2012 22:48:36
#401778
Galera estou desenvolvnnndo um sistema escolar e preciso gerar as frequencias dos alunos e depois que criei a rotina abaixo o sistema ficou lento demais..alguem poderia me dar uma dica pra otimizar mais?

Private Sub Gerar_FrequenciasBoletim()

Dim sql As String
Dim sql1 As String
Dim sql2 As String
Dim sql3 As String
Dim registro As New ADODB.Recordset
Dim registro1 As New ADODB.Recordset
Dim registro2 As New ADODB.Recordset
Dim registro3 As New ADODB.Recordset
Dim datamatri As String
Dim datafinal As String
Dim Disciplina As String
Dim faltas As Variant
Dim contador As Variant


For i = 1 To BimestreAtual
DoEvents

sql1 = [Ô]Select fim from Tbl_Bimestres where ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and bimestre = [Ô] & i
registro1.Open sql1, cn, adOpenKeyset, adLockReadOnly

datafinal = Format(registro1([Ô]fim[Ô]), [Ô]mm/dd/yyyy[Ô])

sql = [Ô]Select matricula, data_matri from Aluno Where ano_alu =[ô][Ô] & Anoletivo & [Ô][ô][Ô]
registro.Open sql, cn, adOpenKeyset, adLockReadOnly

Do While registro.EOF = False
DoEvents

contador = contador + 1
datamatri = Format(registro([Ô]data_matri[Ô]), [Ô]mm/dd/yyyy[Ô])
Matricula = registro([Ô]matricula[Ô])


sql2 = [Ô]SELECT matricula, cod_disc, COUNT(frequencia) AS Total [Ô] & _
[Ô] From dbo.Tbl_Frequencia WHERE (frequencia = [ô]F[ô]) [Ô] & _
[Ô] AND (data >= [ô][Ô] & datamatri & [Ô] [ô]) AND (data <= [ô][Ô] & datafinal & [Ô][ô]) [Ô] & _
[Ô] GROUP BY matricula, cod_disc HAVING (matricula = [ô][Ô] & Matricula & [Ô][ô])[Ô]


registro2.Open sql2, cn, adOpenKeyset, adLockReadOnly

Do While registro2.EOF = False
DoEvents
Disciplina = registro2([Ô]cod_disc[Ô])
faltas = registro2([Ô]Total[Ô])

sql3 = [Ô]SELECT * FROM aluno_disciplina Where ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and matricula =[ô][Ô] & Matricula & [Ô][ô] and cod_disc = [ô][Ô] & Disciplina & [Ô][ô][Ô]
registro3.Open sql3, cn, adOpenKeyset, adLockPessimistic

If registro3.RecordCount > 0 Then

If i = 1 Then
registro3([Ô]falta1[Ô]) = faltas
registro3.Update
registro3.Close
End If


If i = 2 Then
registro3([Ô]falta2[Ô]) = faltas
registro3.Update
registro3.Close
End If

If i = 3 Then
registro3([Ô]falta3[Ô]) = faltas
registro3.Update
registro3.Close
End If


If i = 4 Then

registro3([Ô]falta4[Ô]) = faltas
registro3.Update
registro3.Close

End If

Else

registro3.Close

End If


registro2.MoveNext

Loop

registro2.Close
lbl_aluno.Caption = [Ô]Total processado: [Ô] & contador
registro.MoveNext


Loop

Next i

Call ArredondarFrequencia


End Sub
FILMAN 11/05/2012 08:42:03
#401787
Private Sub Gerar_FrequenciasBoletim()
Dim SQL As String
Dim registro As New ADODB.Recordset
Dim registro1 As New ADODB.Recordset
Dim registro2 As New ADODB.Recordset
Dim registro3 As New ADODB.Recordset
Dim datamatri As String
Dim datafinal As String
Dim Disciplina As String
Dim faltas As Variant
Dim contador As Long

contador = 0
For i = 1 To BimestreAtual
DoEvents
SQL = [Ô]SELECT fim FROM Tbl_Bimestres WHERE ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and bimestre = [Ô] & i
registro1.Open SQL, cn, adOpenStatic, adLockReadOnly
datafinal = Format(registro1([Ô]fim[Ô]), [Ô]mm/dd/yyyy[Ô])
If registro1.State <> 0 Then registro1.Close: Set registro1 = Nothing

SQL = [Ô]SELECT matricula, data_matri FROM Aluno WHERE ano_alu =[ô][Ô] & Anoletivo & [Ô][ô][Ô]
registro.Open SQL, cn, adOpenStatic, adLockReadOnly

Do While Not registro.EOF
contador = contador + 1
datamatri = Format(registro([Ô]data_matri[Ô]), [Ô]mm/dd/yyyy[Ô])
Matricula = registro([Ô]matricula[Ô])

SQL = [Ô]SELECT matricula, cod_disc, COUNT(frequencia) AS Total [Ô] & _
[Ô] FROM dbo.Tbl_Frequencia WHERE (frequencia = [ô]F[ô]) [Ô] & _
[Ô] AND (data BETWEEN #[Ô] & datamatri & [Ô]# AND data #[Ô] & datafinal & [Ô]#) [Ô] & _
[Ô] GROUP BY matricula, cod_disc HAVING (matricula = [ô][Ô] & Matricula & [Ô][ô])[Ô]

registro2.Open SQL, cn, adOpenStatic, adLockReadOnly

Do While Not registro2.EOF
Disciplina = registro2([Ô]cod_disc[Ô])
faltas = registro2([Ô]Total[Ô])

SQL = [Ô]SELECT * FROM aluno_disciplina Where ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and matricula =[ô][Ô] & Matricula & [Ô][ô] and cod_disc = [ô][Ô] & Disciplina & [Ô][ô][Ô]
registro3.Open SQL, cn, adOpenKeyset, adLockPessimistic

If Not registro3.EOF Then
Select Case i
Case 1
registro3([Ô]falta1[Ô]) = faltas
registro3.Update
registro3.Close: Set registro3 = Nothing
Case 2
registro3([Ô]falta2[Ô]) = faltas
registro3.Update
registro3.Close: Set registro3 = Nothing
Case 3
registro3([Ô]falta3[Ô]) = faltas
registro3.Update
registro3.Close: Set registro3 = Nothing
Case 4
registro3([Ô]falta4[Ô]) = faltas
registro3.Update
registro3.Close: Set registro3 = Nothing
Case Else
If registro3.State <> 0 Then registro3.Close: Set registro3 = Nothing
End Select
End If
registro2.MoveNext
DoEvents
Loop

If registro2.State <> 0 Then registro2.Close: Set registro2 = Nothing
lbl_aluno.Caption = [Ô]Total processado: [Ô] & contador
registro.MoveNext
DoEvents
Loop
If registro.State <> 0 Then registro.Close: Set registro = Nothing
Next i
Call ArredondarFrequencia
End Sub


Tenta assim mais acho que não vai resolver muito não vc esta usando qual banco

Percebi que suas tabelas não estão normalizadas tente normaliza-las e indexar os campos que você utiliza para consultar
AMELORP 11/05/2012 09:48:59
#401790
SQL server.
MARCELO.TREZE 11/05/2012 11:08:07
#401797
a principio algo que melhorar o desempenho é colocar os campos na query então você pode fazer esta mudança na sql3:

sql3 = [Ô]SELECT anu_alu, matricula, cod_disc, falta1, falta2, falta3, falta4 FROM aluno_disciplina Where ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and matricula =[ô][Ô] & Matricula & [Ô][ô] and cod_disc = [ô][Ô] & Disciplina & [Ô][ô][Ô]
registro3.Open sql3, cn, adOpenKeyset, adLockPessimistic


repare que coloquei apenas os nomes dos campos usados antes do from

AMELORP 11/05/2012 11:58:00
#401802
Obrigado...será que usando recordset seria o melhor caminho?

Citação:

:
a principio algo que melhorar o desempenho é colocar os campos na query então você pode fazer esta mudança na sql3:

sql3 = [Ô]SELECT anu_alu, matricula, cod_disc, falta1, falta2, falta3, falta4 FROM aluno_disciplina Where ano_alu = [ô][Ô] & Anoletivo & [Ô][ô] and matricula =[ô][Ô] & Matricula & [Ô][ô] and cod_disc = [ô][Ô] & Disciplina & [Ô][ô][Ô]
registro3.Open sql3, cn, adOpenKeyset, adLockPessimistic


repare que coloquei apenas os nomes dos campos usados antes do from

MARCELO.TREZE 11/05/2012 12:37:23
#401805
Primeiro a alteração melhorou algo no desempenho?

a maneira que está utilizando é a mais rápida, porém você está fazendo consulta em 3 tabelas para atualizar 1, o ideal seria reduzir isto a apenas um update com select e inner join, meio complexo mas um pouco mais eficiente, pois não teria de abrir varias conexões para utiliza-la.

algo meio complexo porém mais eficiente



IRENKO 11/05/2012 12:56:39
#401809
Talvez seja o DoEvents! Retire-os e teste.
MARCELO.TREZE 11/05/2012 14:00:51
#401817
Outro questão está na estrutura da tabela, reparando bem na tabela bimestre você possui os bimestres ex:

bimestre
1
2
3
4

e na tabela aluno_disciplina você possui falta1, falta2... o que de deduzo ser falta no 1 bimestre, no 2 bimestre...etc, neste caso o idael seria criar um campo bimestre nesta tabela, ou seja

ao invés de

Falta1 Falta2 Falta3 Falta4
10 13 16 12

ficaria assim

Biomestre Faltas
1 10
2 13
3 16
4 12

o que dispensaria o Laço for para atualizações, exemplo

UPDATE aluno_disciplina AD SET
AD.bimestre = TB.Bimestre
FROM
aluno_disciplina AD INNER JOIN tbl_bimestre TB ON AD.ano_alu = TB.ano_alu


lógico a query acima é apenas para fim ilustrativo, porém a query funcional ficaria próximo disto





AJSO 11/05/2012 14:35:45
#401820
Caro AMELORP

Citação:

:
Dim registro As New ADODB.Recordset
Dim registro1 As New ADODB.Recordset
Dim registro2 As New ADODB.Recordset
Dim registro3 As New ADODB.Recordset



Todos os recordset estão sendo abertos não fechados...............

A forma como escreveu seu código nessa lógica fica difícil obter melhor performance pois como descreveu é uma uma estrutura PIVOT no SQL.

Nessa forma de extração de dados em um único processo em loop há sobrecarrega em memória no executável e ficas lento,

Você esta abrindo Recordset dentro de Outro em Loop.

Esse processo pode melhorar se executado integralmente no Banco em uma Procedure Referenciada ou várias procedures em cascata.

Uma melhoria seria escrever em uma procedure instanciando seus recordset para cursores dentro da procedure con certeza melhoraria sua performance
e os retornos de cada cursor para um Dataset ou Datatable, melhoraria a performance pois o processo fica no Banco...........

Uma segunda forma seria Transformar cada RecordSet em um Function ou Sub com Parametros de referencia para ser chamada em cascata ou nível, melhoraria pois seria para cada processo abre e fecha a conexão.


Boa sorte.
Tópico encerrado , respostas não são mais permitidas