Depois de ler o artigo a seguir, descobri que o teste do autor é realmente útil para amigos que usam ASP. Ele deve ser semelhante não apenas para ASP, mas também para outras linguagens. A geração de conteúdo dinâmico no servidor é um dos principais motivos para usar ASP, portanto, o primeiro projeto de teste que escolhemos foi determinar o melhor método para enviar conteúdo dinâmico para o fluxo de resposta. Existem duas opções básicas (e algumas variações delas): usar tags ASP embutidas e usar a instrução Response.Write.
Para testar essas diferentes abordagens, criamos uma página ASP simples que definia algumas variáveis e depois as inserimos em uma tabela. Embora esta página seja simples e sem utilidade prática, é suficiente para nos permitir isolar e testar problemas individuais.
2.1 Usando tags embutidas ASP
O primeiro teste é usar a tag inline do ASP <%= x %>, onde x é uma variável. Este é o método mais conveniente de usar e torna a parte HTML da página mais fácil de ler e manter.
Copie o código do código da seguinte forma:
<% OPÇÃO EXPLÍCITA
Dim PrimeiroNome
DimSobrenome
Dim MédioInicial
Endereço escuro
Cidade escura
Estado escuro
DimPhoneNumber
Escurecer número de fax
Escurecer e-mail
DimDataDeNascimento
Nome = João
MédioInicial = Q
Sobrenome = Público
Endereço = Rua Principal 100
Cidade=Nova York
Estado=NY
Número de telefone = 1-212-555-1234
Número de fax = 1-212-555-1234
E-mail = [email protected]
Data de nascimento = 01/01/1950
%>
<HTML>
<CABEÇA>
<TITLE>Teste de resposta</TITLE>
</HEAD>
<CORPO>
<H1>Teste de Resposta</H1>
<TABELA>
<tr><td><b>Nome:</b></td><td><%= Nome %></td></tr>
<tr><td><b>Inicial do meio:</b></td><td><%= MiddleInitial %></td></tr>
<tr><td><b>Sobrenome:</b></td><td><%= Sobrenome %></td></tr>
<tr><td><b>Endereço:</b></td><td><%= Endereço %></td></tr>
<tr><td><b>Cidade:</b></td><td><%= Cidade %></td></tr>
<tr><td><b>Estado:</b></td><td><%= Estado %></td></tr>
<tr><td><b>Número de telefone:</b></td><td><%= Número de telefone %></td></tr>
<tr><td><b>Número de fax:</b></td><td><%=Número de fax %></td></tr>
<tr><td><b>E-mail:</b></td><td><%= E-mail %></td></tr>
<tr><td><b>Data de nascimento:</b></td><td><%= Data de nascimento %></td></tr>
</TABELA>
</BODY>
</HTML>
O código completo de /app1/response1.asp
Melhor registro = 8,28 ms/página
2.2 Use Response.Write para gerar cada linha de código HTML
Há muita literatura boa por aí que afirma que a abordagem de marcação inline anterior deve ser evitada porque resulta em uma operação chamada troca de contexto. Esta operação ocorre quando o tipo de código processado pelo servidor web muda (de envio de HTML puro para processamento de script, ou vice-versa), e essa mudança leva um certo tempo. Depois que muitos programadores aprendem isso, sua primeira reação é usar a função Response.Write para gerar cada linha de código HTML:
Copie o código do código da seguinte forma:
...
Resposta.Write(<html>)
Resposta.Write(<head>)
Response.Write( <title>Teste de resposta</title>)
Resposta.Write(</head>)
Response.Write(<corpo>)
Response.Write(<h1>Teste de resposta</h1>)
Response.Write(<tabela>)
Response.Write(<tr><td><b>Nome:</b></td><td> & Nome & </td></tr>)
Response.Write(<tr><td><b>Inicial do meio:</b></td><td> & MiddleInitial & </td></tr>)
...
Fragmento /app1/response2.asp
Melhor registro = 8,28 ms/página
Tempo de resposta = 8,08 ms/página
Diferença = -0,20 ms (redução de 2,4%)
A melhoria de desempenho que vimos em comparação com a versão de marcação inline foi tão pequena que foi simplesmente surpreendente. Isso pode ocorrer porque há muito mais chamadas de função na página. No entanto, este método tem uma desvantagem maior, uma vez que o código HTML está incorporado na função, o código do script torna-se muito longo e inconveniente para ler e manter.
2.3 Use funções wrapper
Response.Write não adiciona CRLF (Carriage Return - Line Feed, Carriage Return - Line Feed) no final da linha de texto, o que é o aspecto mais decepcionante do uso do método acima. Embora o código HTML tenha sido bem formatado no lado do servidor, o que você vê no navegador ainda é apenas uma longa linha de código. Mas esse problema não foi a única decepção. As pessoas logo descobriram que não havia uma função Response.WriteLn que pudesse adicionar CRLF automaticamente. Uma reação natural é criar uma função wrapper para Response.Write e adicionar CRLF após cada linha:
...
writeCR(<tr><td><b>Nome:</b></td><td> & Nome & </td></tr>)
...
SUB gravaçãoCR(str)
Resposta.Write(str & vbCRLF)
FINALIZAR SUB
Fragmento /app1/response4.asp
Melhor registro = 8,08 ms/página
Tempo de resposta = 10,11 ms/página
Diferença = +2,03 ms (aumento de 25,1%)
O resultado é uma diminuição significativa no desempenho. Claro, isso ocorre principalmente porque esse método dobra o número de chamadas de função e seu impacto no desempenho é muito óbvio. Esse uso deve ser evitado a todo custo, o CRLF resulta em dois bytes extras no final de cada linha, e esses dois bytes são inúteis para o navegador exibir a página. Na maioria dos casos, o belo formato do código HTML do navegador apenas torna mais fácil para seus concorrentes lerem e compreenderem o design da página.
2.4 Mesclar vários Response.Write
Ignorando o último teste sobre encapsulamento de funções, o próximo passo lógico seria mesclar todas as strings de instruções Response.Write separadas em uma instrução, reduzindo assim o número de chamadas de função e melhorando a eficiência do código.
Copie o código do código da seguinte forma:
Resposta.Write(<html> & _
<cabeça> & _
<title>Teste de resposta</title> & _
</head> & _
<corpo> & _
<h1>Teste de resposta</h1> & _
<tabela> & _
<tr><td><b>Nome:</b></td><td> & Nome & </td></tr> & _
...
<tr><td><b>Data de nascimento:</b></td><td> & Data de nascimento & </td></tr> & _
</tabela> & _
</body> & _
</html>)
Fragmento /app1/response3.asp
Melhor registro = 8,08 ms/página
Tempo de resposta = 7,05 ms/página
Diferença = -1,03 ms (redução de 12,7%)
Este é de longe o melhor método.
2.5 Combine vários Response.Write e adicione CRLF no final de cada linha
Algumas pessoas também estão muito preocupadas se seu código HTML fica bonito no lado do navegador, então adicionamos um retorno de carro no final de cada linha do código HTML, usando a constante vbCRLF. Os outros códigos de teste são iguais ao exemplo acima. .
...
Response.Write(<html> & vbCRLF & _
<head> & vbCRLF & _
<title>Teste de resposta</title> & vbCRLF & _
</head> & vbCRLF & _
...
Fragmento /app1/response5.asp
Melhor registro = 7,05 ms/página
Tempo de resposta = 7,63 ms/página
Diferença = +0,58 ms (aumento de 8,5%)
O resultado é uma ligeira diminuição no desempenho, provavelmente devido à adição de operações de concatenação de strings e ao aumento no texto de saída.
2.6 Comentários
Com base nos resultados do teste de saída ASP acima, chegamos às seguintes regras de codificação:
Evite usar muito ASP incorporado.
Combine tantas instruções Response.Write quanto possível em uma única instrução.
Nunca encapsule Response.Write apenas para adicionar CRLF.
Se você deseja formatar a saída HTML, adicione CRLF diretamente após a instrução Response.Write.
Esboço: Qual é a maneira mais eficiente de gerar conteúdo gerado dinamicamente por ASP? Qual é a melhor maneira de extrair um conjunto de registros de banco de dados? Este artigo testa quase 20 problemas comuns nesse desenvolvimento ASP. O tempo exibido pela ferramenta de teste nos diz: esses problemas que geralmente são considerados normais não são apenas dignos de atenção, mas também contêm segredos inesperados.
1. Finalidade do teste
A primeira parte deste artigo examina algumas questões básicas no desenvolvimento ASP e fornece alguns resultados de testes de desempenho para ajudar os leitores a compreender o impacto que o código colocado na página tem no desempenho. ADO é uma interface de banco de dados universal e fácil de usar desenvolvida pela Microsoft. Acontece que a interação com o banco de dados por meio do ADO é uma das aplicações mais importantes do ASP.
A funcionalidade disponibilizada pelo ADO é bastante extensa, portanto a maior dificuldade na preparação deste artigo é como definir o escopo do problema. Considerando que a extração de grandes quantidades de dados pode aumentar significativamente a carga no servidor Web, decidimos que o objetivo principal desta seção é descobrir qual é a configuração ideal para operar conjuntos de registros ADO. Porém, mesmo depois de estreitar o escopo do problema, ainda enfrentamos grandes dificuldades, pois o ADO pode ter muitas maneiras diferentes de realizar a mesma tarefa. Por exemplo, os conjuntos de registros podem ser extraídos não apenas por meio da classe Recordset, mas também pelas classes Connection e Command, mesmo após a obtenção do objeto recordset, existem muitos métodos de operação que podem afetar drasticamente o desempenho; Contudo, tal como na Parte Um, tentaremos cobrir a gama mais ampla possível de questões.
Especificamente, o objetivo desta seção é reunir informações suficientes para responder às seguintes questões:
O ADOVBS.inc deve ser referenciado por meio de inclusão?
lDevo criar um objeto de conexão separado ao usar conjuntos de registros?
lQual é a melhor maneira de extrair um conjunto de registros?
lQual tipo de cursor e método de bloqueio de registro são mais eficientes?
lDevo usar um conjunto de registros local?
lQual é a melhor maneira de definir as propriedades do conjunto de registros?
lQual método é mais eficiente para referenciar valores de campo em um conjunto de registros?
É uma boa maneira de coletar saída com string temporária?
2. Ambiente de teste
Um total de 21 arquivos ASP foram usados neste teste, que podem ser baixados no final deste artigo. Cada página está configurada para executar três consultas diferentes, retornando 0, 25 e 250 registros respectivamente. Isso nos ajudará a isolar a sobrecarga de inicialização e execução da própria página da sobrecarga de loop no conjunto de registros.
Para facilitar o teste, a cadeia de conexão do banco de dados e a cadeia de comando SQL são salvas como variáveis de aplicativo em Global.asa. Como nosso banco de dados de teste é o SQL Server 7.0, a cadeia de conexão especifica OLEDB como o provedor de conexão e os dados de teste vêm do banco de dados Northwind do SQL Server. O comando SQL SELECT extrai 7 campos especificados da tabela NorthWind Orders.
Copie o código do código da seguinte forma:
<SCRIPT LANGUAGE=VBScript RUNAT=Servidor>
Subaplicativo_OnStart
Aplicativo(Conn) = Provedor=SQLOLEDB & _
Servidor=MeuServidor;
uid=sa;
senha=;
BANCO DE DADOS = vento norte
Aplicativo (SQL) = SELECTTOP 0OrderID, & _
ID do cliente, & _
ID do funcionário, & _
Data do pedido, & _
Data obrigatória, & _
Data de envio, & _
Frete e _
DE[Pedidos]
Finalizar sub
</SCRIPT>
'sql alternativo - 25 registros
Aplicativo (SQL) = SELECTTOP 25OrderID, & _
ID do cliente, & _
ID do funcionário, & _
Data do pedido, & _
Data obrigatória, & _
Data de envio, & _
Frete e _
DE[Pedidos]
'registros sql-250 alternativos
Aplicativo (SQL) = SELECTTOP 250 OrderID, & _
ID do cliente, & _
ID do funcionário, & _
Data do pedido, & _
Data obrigatória, & _
Data de envio, & _
Frete e _
DE[Pedidos]
A configuração do servidor de teste foi a seguinte: Pentium de 450 Mhz, 512 MB de RAM, NT Server 4.0 SP5, MDAC 2.1 (Data Access Component) e Microsoft Scripting Engine versão 5.0. O SQL Server está sendo executado em outra máquina com configuração semelhante. Assim como na primeira parte, ainda utilizamos o Microsoft Web Application Stress Tool para registrar o tempo desde a solicitação da primeira página até o último byte recebido do servidor (TTLB, Time To Last Byte), o tempo é em milissegundos. O script de teste chamou cada página mais de 1.300 vezes e levou cerca de 20 horas para ser executado. Os tempos mostrados abaixo são o TTLB médio da sessão. Lembre-se, como na primeira parte, estamos preocupados apenas com a eficiência do código, não com sua escalabilidade ou desempenho do servidor.
Observe também que habilitamos o buffer do servidor. Além disso, para que todos os nomes de arquivos tenham o mesmo comprimento, alguns nomes de arquivos possuem um ou mais sublinhados incorporados.
3. Primeiro teste
No primeiro teste, extraímos um conjunto de registros simulando um cenário típico encontrado nas amostras do Microsoft ASP ADO. Neste exemplo (ADO__01.asp), primeiro abrimos uma conexão e depois criamos o objeto recordset. Claro, o script aqui é otimizado de acordo com as regras de codificação resumidas na primeira parte deste artigo.
Copie o código do código da seguinte forma:
<% Opção Explícita %>
<!-- #Incluir arquivo=ADOVBS.INC -->
<%
Dim objConn
Dim objRS
Resposta.Write(_
<HTML><HEAD> & _
<TITLE>Teste ADO</TITLE> & _
</HEAD><BODY> _
)
Definir objConn = Server.CreateObject(ADODB.Connection)
objConn.Open Application (Conn)
Definir objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.Aplicativo aberto (SQL)
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever títulos
Resposta.Write(_
<BORDA DA TABELA=1> & _
<TR> & _
<TH>ID do pedido</TH> & _
<TH>CustomerID</TH> & _
<TH>ID do funcionário</TH> & _
<TH>Data do pedido</TH> & _
<TH>Data Obrigatória</TH> & _
<TH>Data de Envio</TH> & _
<TH>Frete</TH> & _
</TR> _
)
'grava dados
Faça enquanto não objRS.EOF
Resposta.Write(_
<TR> & _
<TD> & objRS(OrderID) & </TD> & _
<TD> & objRS(CustomerID) & </TD> & _
<TD> & objRS(EmployeeID) & </TD> & _
<TD> & objRS(DataPedido) & </TD> & _
<TD> & objRS(DataObrigatória) & </TD> & _
<TD> & objRS(Data de envio) & </TD> & _
<TD> & objRS(Frete) & </TD> & _
</TR> _
)
objRS.MoveNext
Laço
Resposta.Write(</TABLE>)
Terminar se
objRS.Fechar
objConn.Fechar
Definir objRS = Nada
Definir objConn = Nada
Resposta.Write(</BODY></HTML>)
%>
Aqui estão os resultados do teste:
Vamos dar uma olhada no significado dos números em cada coluna:
0 retorna o TTLB (em milissegundos) necessário para uma página com 0 registros. Em todos os testes, esse valor é considerado o tempo gasto na geração da própria página (incluindo a criação de objetos), excluindo o tempo de iteração pelos dados do conjunto de registros.
25 TTLB em milissegundos para buscar e exibir 25 registros
O TTLB na coluna tot time/2525 é dividido por 25, que é o custo médio total de tempo por registro.
disp time/2525 coluna TTLB menos 0 coluna TTLB e depois divida por 25. Esse valor reflete o tempo necessário para exibir um único registro durante o loop pelo conjunto de registros.
250 Extrai e exibe TTLB de 250 registros.
O TTLB na coluna tot time/250250 é dividido por 25. Esse valor representa o custo médio total de tempo de um único registro.
disp time/250 O TTLB na coluna 250 é subtraído do TTLB na coluna 0 e depois dividido por 250. Esse valor reflete o tempo necessário para exibir um único registro durante o loop pelo conjunto de registros.
Os resultados do teste acima serão usados para comparar com os próximos resultados do teste.
4. O ADOVBS.inc deve ser referenciado por meio de inclusão?
ADOVBS.inc fornecido pela Microsoft contém 270 linhas de código que definem a maioria das constantes de propriedade ADO. Nosso exemplo faz referência apenas a 2 constantes de ADOVBS.inc. Portanto, neste teste (ADO__02.asp) excluímos a referência de arquivo incluída e usamos diretamente o valor correspondente ao definir as propriedades.
objRS.CursorType = 0?'
objRS.LockType = 1' adLockReadOnly
Você pode ver que a sobrecarga da página caiu 23%. Esse valor não afeta o tempo de busca e exibição de registros individuais, pois as alterações aqui não afetam as operações do conjunto de registros dentro do loop. Existem várias maneiras de resolver problemas de referência do ADOVBS.inc. Recomendamos usar o arquivo ADOVBS.inc como referência e explicar as configurações por meio de comentários. Lembre-se, conforme observado na Parte 1, o uso moderado de comentários tem impacto mínimo na eficiência do seu código. Outro método é copiar as constantes necessárias do arquivo ADOVBS.inc para a página.
Também existe uma boa maneira de resolver esse problema, que é disponibilizar diretamente todas as constantes do ADO vinculando-as à biblioteca de tipos do ADO. Adicione o seguinte código ao arquivo Global.asa para acessar diretamente todas as constantes ADO:
<!--METADATA TYPE=typelib
FILE=C:Arquivos de ProgramasArquivos ComunsSYSTEMADOmsado15.dll
NAME=Biblioteca de tipos ADODB -->
ou:
<!--METADATA TYPE=typelib
UUID=00000205-0000-0010-8000-00AA006D2EA4
NAME=Biblioteca de tipos ADODB -->
Portanto, nossa primeira regra é:
lEvite incluir o arquivo ADOVBS.inc e acesse e use constantes ADO por meio de outros métodos.
5. Devo criar um objeto de conexão separado ao usar um conjunto de registros?
Para responder corretamente a esta pergunta, devemos analisar o teste sob duas condições diferentes: primeiro, a página possui apenas uma transação de banco de dados; segundo, a página possui múltiplas transações de banco de dados;
No exemplo anterior, criamos um objeto Connection separado e o atribuímos à propriedade ActiveConnection do Recordset. Entretanto, conforme mostrado em ADO__03.asp, também podemos atribuir a string de conexão diretamente à propriedade ActiveConnection, eliminando a etapa adicional de inicialização e configuração do objeto Connection no script.
objRS.ActiveConnection = Aplicativo (Conn)
Embora o objeto Recordset ainda precise criar uma conexão, a criação neste momento é realizada em condições altamente otimizadas. Como resultado, a sobrecarga da página caiu mais 23% em comparação com o teste anterior e, como esperado, o tempo de exibição de um único registro não mudou substancialmente.
Portanto, nossa segunda regra é a seguinte:
lSe você usar apenas um conjunto de registros, atribua diretamente a cadeia de conexão à propriedade ActiveConnection.
A seguir, verificamos se as regras acima ainda são válidas quando a página usa vários conjuntos de registros. Para testar esta situação, introduzimos um loop FOR para repetir o exemplo anterior 10 vezes. Neste teste, veremos três variações:
Primeiro, conforme mostrado em ADO__04.asp, o objeto Connection é estabelecido e destruído em cada loop:
Copie o código do código da seguinte forma:
Escureça eu
Para eu = 1 a 10
Definir objConn = Server.CreateObject(ADODB.Connection)
objConn.Open Application (Conn)
Definir objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Aplicativo aberto (SQL)
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever títulos
...
'grava dados
...
Terminar se
objRS.Fechar
Definir objRS = Nada
objConn.Fechar
Definir objConn = Nada
Próximo
Segundo, conforme mostrado em ADO__05.asp, crie um objeto Connection fora do loop e compartilhe esse objeto com todos os conjuntos de registros:
Copie o código do código da seguinte forma:
Definir objConn = Server.CreateObject(ADODB.Connection)
objConn.Open Application (Conn)
Escureça eu
Para eu = 1 a 10
Definir objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Aplicativo aberto (SQL)
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever títulos
...
'grava dados
...
Terminar se
objRS.Fechar
Definir objRS = Nada
Próximo
objConn.Fechar
Definir objConn = Nada
Terceiro, conforme mostrado em ADO__06.asp, atribua a cadeia de conexão à propriedade ActiveConnection em cada loop:
Copie o código do código da seguinte forma:
Escureça eu
Para eu = 1 a 10
Definir objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = Aplicativo (Conn)
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Aplicativo aberto (SQL)
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever títulos
...
'grava dados
...
Terminar se
objRS.Fechar
Definir objRS = Nada
Próximo
Como podemos imaginar, criar e destruir objetos de conexão dentro de um loop é a maneira menos eficiente. Surpreendentemente, entretanto, atribuir a cadeia de conexão diretamente à propriedade ActiveConnection dentro do loop é apenas um pouco mais lento do que compartilhar um único objeto Connection.
No entanto, a terceira regra deve ser:
lQuando vários conjuntos de registros são usados na mesma página, crie um único objeto de conexão e compartilhe-o por meio da propriedade ActiveConnection.
6. Qual tipo de cursor e método de bloqueio de registro são mais eficientes?
Em todos os testes até agora, usamos apenas cursores somente de avanço para acessar o conjunto de registros. Existem três tipos de cursores fornecidos pelo ADO para conjuntos de registros: cursores estáticos com rolagem, cursores dinâmicos com rolagem e cursores de conjunto de chaves. Cada cursor oferece funções diferentes, como acessar o registro anterior e o próximo registro, se você pode ver modificações nos dados por outros programas, etc. Entretanto, uma discussão detalhada das funções de cada tipo de cursor está além do escopo deste artigo. A tabela a seguir é uma análise comparativa de vários tipos de cursor.
Todos os outros tipos de cursor requerem sobrecarga adicional em comparação com cursores somente de avanço, e esses cursores geralmente são mais lentos em loops. Portanto, gostaríamos de compartilhar com vocês a seguinte advertência: Nunca pense assim - bem, às vezes usarei cursores dinâmicos, então sempre usarei este cursor.
O mesmo sentimento se aplica à escolha do método de bloqueio de registro. O teste anterior usou apenas o método de bloqueio somente leitura, mas existem três outros métodos: processamento em lote conservador, aberto e aberto. Assim como os tipos de cursor, esses métodos de bloqueio fornecem funcionalidade e controle diferentes sobre o trabalho com dados do conjunto de registros.
Chegamos às seguintes regras:
lUse o tipo de cursor mais simples e o método de bloqueio de registro adequado para a tarefa.
7. Qual método é melhor usar para extrair um conjunto de registros?
Até agora extraímos conjuntos de registros criando objetos Recordset, mas o ADO também fornece métodos indiretos de extração de conjuntos de registros. O teste a seguir compara ADO__03.asp e a criação de um conjunto de registros diretamente do objeto Connection (CONN_01.asp):
Copie o código do código da seguinte forma:
Definir objConn = Server.CreateObject(ADODB.Connection)
objConn.Open Application (Conn)
Definir objRS = objConn.Execute(Application(SQL))
Você pode ver que a sobrecarga da página aumentou ligeiramente e o tempo de exibição de um único registro não mudou.
Vamos dar uma olhada na criação de um objeto recordset (CMD__02.asp) diretamente do objeto Command:
Copie o código do código da seguinte forma:
Definir objCmd = Server.CreateObject(ADODB.Command)
objCmd.ActiveConnection = Aplicativo (Conn)
objCmd.CommandText = Aplicativo (SQL)
Definir objRS = objCmd.Execute
Da mesma forma, a sobrecarga da página aumenta ligeiramente sem alteração substancial no tempo de exibição de um único registro. A diferença de desempenho entre os dois últimos métodos é pequena, mas temos uma questão importante a considerar.
Ao criar um conjunto de registros por meio da classe Recordset, podemos controlar o processamento do conjunto de registros com maior flexibilidade. Como os dois últimos métodos não conseguem atingir um desempenho impressionante, consideramos principalmente o tipo de cursor e o método de bloqueio de registro retornados por padrão. Em algumas ocasiões, o valor padrão não é necessariamente o mais ideal.
Portanto, a menos que existam razões especiais para escolher entre os dois últimos métodos, recomendamos considerar as seguintes regras:
l Instancie o conjunto de registros por meio da classe ADODB.Recordset para obter o melhor desempenho e flexibilidade.
8. Devo usar um conjunto de registros local?
O ADO permite o uso de conjuntos de registros locais (cliente). Neste momento, a consulta extrairá todos os dados do conjunto de registros. Após a conclusão da consulta, a conexão pode ser fechada imediatamente e os cursores locais podem ser usados para acessar os dados. o futuro, o que traz comodidade para liberar a conexão. O uso de conjuntos de registros locais é importante para acessar serviços de dados remotos que exigem que os dados sejam usados off-line, mas também será útil para aplicativos comuns?
A seguir adicionamos o atributo CursorLocation e fechamos a conexão (CLIENT1.asp) após abrir o recordset:
Copie o código do código da seguinte forma:
Definir objRS = Server.CreateObject(ADODB.Recordset)
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = Aplicativo (Conn)
objRS.LockType = 1?'
objRS.Aplicativo aberto (SQL)
objRS.ActiveConnection = Nada
Em teoria, esta abordagem beneficiaria a eficiência por duas razões: primeiro, evita a solicitação repetida de dados através da conexão ao mover-se entre registros; segundo, facilita os requisitos de recursos; No entanto, parece na tabela acima que o uso do conjunto de registros local obviamente não ajudará a melhorar a eficiência. Isso pode ocorrer porque, ao usar um conjunto de registros local, o cursor sempre se torna um tipo estático, independentemente das configurações do programa.
A regra 6 é a seguinte:
lIsso deve ser evitado, a menos que a localização do conjunto de registros seja realmente necessária.
10. Qual método é mais eficiente para fazer referência a valores de campo em um conjunto de registros?
10.1 Teste
Até agora nos referimos aos valores dos campos no conjunto de registros por nome. Como esse método exige sempre encontrar o campo correspondente, ele não é muito eficiente. Para demonstrar isso, no teste a seguir referenciamos o valor de um campo pelo seu índice na coleção (ADO__08.asp):
Copie o código do código da seguinte forma:
'grava dados
Faça enquanto não objRS.EOF
Resposta.Write(_
<TR> & _
<TD> & objRS(0) & </TD> & _
<TD> & objRS(1) & </TD> & _
<TD> & objRS(2) & </TD> & _
<TD> & objRS(3) & </TD> & _
<TD> & objRS(4) & </TD> & _
<TD> & objRS(5) & </TD> & _
<TD> & objRS(6) & </TD> & _
</TR> _
)
objRS.MoveNext
Laço
Como esperado, há também uma pequena alteração no overhead da página (talvez devido a uma ligeira redução no código). No entanto, a melhoria no tempo de exibição com esta abordagem é bastante perceptível.
No próximo teste, vinculamos todos os campos às variáveis individualmente (ADO__09.asp):
Copie o código do código da seguinte forma:
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever títulos
...
Escurecer fld0
Escurecer fld1
Escurecer fld2
Escurecer fld3
Escurecer fld4
Escurecer fld5
Escurecer fld6
Defina fld0 = objRS(0)
Defina fld1 = objRS(1)
Defina fld2 = objRS(2)
Defina fld3 = objRS(3)
Defina fld4 = objRS(4)
Defina fld5 = objRS(5)
Defina fld6 = objRS(6)
'grava dados
Faça enquanto não objRS.EOF
Resposta.Write(_
<TR> & _
<TD> & fld0 & </TD> & _
<TD> & fld1 & </TD> & _
<TD> & fld2 & </TD> & _
<TD> & fld3 & </TD> & _
<TD> & fld4 & </TD> & _
<TD> & fld5 & </TD> & _
<TD> & fld6 & </TD> & _
</TR> _
)
objRS.MoveNext
Laço
Definir fld0 = Nada
Definir fld1 = Nada
Definir fld2 = Nada
Definir fld3 = Nada
Definir fld4 = Nada
Definir fld5 = Nada
Definir fld6 = Nada
Resposta.Write(</TABLE>)
Terminar se
Este é o melhor registro até agora. Observe que o tempo de exibição de um único registro foi reduzido para menos de 0,45 milissegundos.
Todos os scripts acima requerem alguma compreensão da construção do conjunto de registros de resultados. Por exemplo, usamos nomes de campos diretamente nos cabeçalhos das colunas para fazer referência a cada valor de campo individualmente. No teste a seguir, não apenas os dados do campo são obtidos percorrendo a coleção de campos, mas os títulos dos campos também são obtidos da mesma forma. Esta é uma solução mais dinâmica (ADO__10.asp).
Copie o código do código da seguinte forma:
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
'escrever cabeçalhos Response.Write(<TABLE BORDER=1><TR>)
Para cada objFld em objRS.Fields
Response.Write(<TH> & objFld.name & </TH>)
Próximo
Resposta.Write(</TR>)
'grava dados
Faça enquanto não objRS.EOF
Resposta.Write(<TR>)
Para cada objFld em objRS.Fields
?Resposta.Write(<TD> & objFld.valor & </TD>)
Próximo
Resposta.Write(</TR>)
objRS.MoveNext
Laço
Resposta.Write(</TABLE>)
Terminar se
Como você pode ver, o desempenho do código diminuiu, mas ainda é mais rápido que ADO__07.asp.
O próximo exemplo de teste é um compromisso dos dois métodos anteriores. Continuaremos mantendo o recurso dinâmico enquanto melhoramos o desempenho salvando referências de campo em arrays alocados dinamicamente:
Copie o código do código da seguinte forma:
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
Outro
Dim fldCount
fldCount = objRS.Fields.Count
Escurecer fld()
ReDim fld(fldCount)
Escureça eu
Para i = 0 para fldCount-1
Defina fld(i) = objRS(i)
Próximo
'escrever títulos
Response.Write(<TABLE BORDER=1><TR>) Para i = 0 para fldCount-1
Response.Write(<TH> & fld(i).nome & </TH>)
Próximo
Resposta.Write(</TR>)
'grava dados
Faça enquanto não objRS.EOF
Resposta.Write(<TR>)
Para i = 0 para fldCount-1
Response.Write(<TD> & fld(i) & </TD>)
Próximo
Resposta.Write(</TR>)
objRS.MoveNext
Laço
Para i = 0 para fldCount-1
Defina fld(i) = Nada
Próximo
Resposta.Write(</TABLE>)
Terminar se
Embora não supere o melhor anterior, é mais rápido que os primeiros exemplos e tem a vantagem de processar dinamicamente qualquer conjunto de registros.
Comparado com o código de teste anterior, o código de teste a seguir foi fundamentalmente alterado. Ele usa o método GetRows do objeto Recordset para preencher a matriz para iteração dos dados, em vez de acessar diretamente o próprio Recordset. Observe que o Recordset é definido como Nothing imediatamente após chamar GetRows, o que significa que os recursos do sistema serão liberados o mais rápido possível. Além disso, observe que a primeira dimensão da matriz representa os campos e a segunda dimensão representa as linhas (ADO__12.asp).
Copie o código do código da seguinte forma:
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
objRS.Fechar
Definir objRS = Nada
Outro
'escrever títulos
...
'definir matriz
Dim arrRS
arrRS = objRS.GetRows
'fecha o conjunto de registros mais cedo
objRS.Fechar
Definir objRS = Nada
'grava dados
DimnumRows
DimnumFlds
Linha escura
Escurecer campo
numFlds = Ubound(arrRS, 1)
numRows = Ubound(arrRS, 2)
Para linha = 0 para numRows
Resposta.Write(<TR>)
Para fld = 0 para numFlds
Response.Write(<TD> & arrRS(fld, linha) & </TD>)
Próximo
Resposta.Write(</TR>)
Próximo
Resposta.Write(</TABLE>)
Terminar se
Ao usar o método GetRows, todo o conjunto de registros é extraído em uma matriz. Embora possam ocorrer problemas de recursos quando o conjunto de registros é extremamente grande, o acesso aos dados em um loop é realmente mais rápido porque as chamadas de função como MoveNext e a verificação de EOF são canceladas.
A velocidade tem um custo, agora os metadados do conjunto de registros estão perdidos. Para resolver esse problema, podemos extrair as informações do cabeçalho do objeto recordset antes de chamar GetRows. Além disso, o tipo de dados e outras informações também podem ser extraídos antecipadamente; Observe também que a vantagem de desempenho nos testes ocorre apenas quando o conjunto de registros é maior.
No último teste deste conjunto, utilizamos o método GetString do recordset. O método GetString extrai todo o conjunto de registros em uma string grande e permite especificar o delimitador (ADO__13.asp):
Copie o código do código da seguinte forma:
Se objRS.EOF Então
Response.Write (Nenhum registro encontrado)
objRS.Fechar
Definir objRS = Nada
Outro
'escrever títulos
...
'definir matriz
Dim strTable
strTable = objRS.GetString (2, , </TD><TD>, </TD></TR><TR><TD>)
'fecha o conjunto de registros mais cedo
objRS.Fechar
Definir objRS = Nada
Response.Write(strTable & </TD></TR></TABLE>)
Terminar se