Partilhar via


Usando buffer adaptável

Baixar driver JDBC

O buffering adaptativo foi concebido para recuperar qualquer tipo de dados de grande valor sem a sobrecarga dos cursores do servidor. As aplicações podem usar a funcionalidade de buffering adaptativo com todas as versões do SQL Server suportadas pelo driver.

Normalmente, quando o Driver Microsoft JDBC para SQL Server executa uma consulta, o driver recupera todos os resultados do servidor para a memória da aplicação. Embora esta abordagem minimize o consumo de recursos no SQL Server, pode gerar um OutOfMemoryError na aplicação JDBC para as consultas que produzem resultados muito grandes.

Para permitir que as aplicações lidam com resultados muito grandes, o Microsoft JDBC Driver para SQL Server fornece buffering adaptativo. Com buffering adaptativo, o driver recupera os resultados da execução de instruções do SQL Server conforme a aplicação os precisa, em vez de todos de uma vez. O condutor também descarta os resultados assim que a aplicação já não consegue aceder a eles. Seguem-se alguns exemplos onde o buffering adaptativo pode ser útil:

  • A consulta produz um conjunto de resultados muito grande: A aplicação pode executar uma instrução SELECT que produz mais linhas do que a aplicação pode armazenar na memória. Em versões anteriores, a aplicação tinha de usar um cursor de servidor para evitar um OutOfMemoryError. O buffering adaptativo oferece a capacidade de efetuar uma leitura contínua somente para frente de um conjunto de resultados de tamanho arbitrário sem necessidade de um cursor de servidor.

  • A consulta produz colunasSQLServerResultSet muito grandes ou parâmetro OUT do SQLServerCallableStatement: A aplicação pode recuperar um único valor (coluna ou parâmetro OUT) que é grande demais para caber inteiramente na memória da aplicação. O buffering adaptativo permite à aplicação cliente recuperar tal valor como um fluxo, utilizando os métodos getAsciiStream, getBinaryStream ou getCharacterStream. A aplicação recupera o valor do SQL Server à medida que lê do fluxo de dados.

Observação

Com buffering adaptativo, o driver JDBC bufferiza apenas a quantidade de dados que é necessário. O controlador não fornece qualquer método público para controlar ou limitar o tamanho do buffer.

Definir buffering adaptativo

A partir do driver JDBC versão 2.0, o comportamento padrão do driver é "adaptativo". Ou seja, para obter o comportamento de buffering adaptativo, a sua aplicação não precisa de solicitar explicitamente o comportamento adaptativo. Na versão 1.2, no entanto, o modo de buffering estava "cheio" por padrão e a aplicação tinha de solicitar explicitamente o modo de buffering adaptativo.

Há três maneiras de uma aplicação solicitar que a execução de uma instrução, use a bufferização adaptativa:

Ao usar o driver JDBC versão 1.2, as aplicações precisavam de lançar o objeto de instrução para uma classe SQLServerStatement para usar o método setResponseBuffering . Os exemplos de código nos exemplos de leitura de dados grandes e exemplo de leitura de grandes volumes de dados com procedimentos armazenados demonstram este uso antigo.

No entanto, com o driver JDBC versão 2.0, as aplicações podem usar o método isWrapperFor e o método unwrap para aceder à funcionalidade específica do fornecedor sem qualquer suposição sobre a hierarquia de classes de implementação. Para obter um exemplo de código, consulte o tópico Atualização de uma grande amostra de dados.

Recuperação de grandes volumes de dados com buffering adaptativo

Quando valores grandes são lidos uma vez usando os métodos get<Type>Stream, e as colunas ResultSet e os parâmetros CallableStatement OUT são acessados na ordem devolvida pelo SQL Server, o buffering adaptativo minimiza o uso de memória da aplicação enquanto processa os resultados. Ao utilizar buffering adaptativo:

  • Os métodos get<>Type Stream, definidos nas classes SQLServerResultSet e SQLServerCallableStatement, retornam streams de leitura única por padrão, embora possam ser reiniciados se forem marcados pela aplicação. Se a aplicação quiser reset o fluxo, tem de primeiro chamar o mark método nesse fluxo.

  • Os métodos get<>Type Stream definidos nas classes SQLServerClob e SQLServerBlob retornam fluxos que podem sempre ser reposicionados para a posição inicial do fluxo sem chamar o mark método.

Quando a aplicação utiliza buffering adaptativo, os valores recuperados pelos métodos get<Type>Stream só podem ser recuperados uma vez. Se tentar chamar qualquer método get<Type> na mesma coluna ou parâmetro depois de chamar o método get<Type>Stream do mesmo objeto, é lançada uma exceção com a mensagem, "Os dados foram acedidos e não estão disponíveis para esta coluna ou parâmetro".

Observação

Uma chamada ao ResultSet.close() a meio do processamento de um ResultSet exigiria que o Microsoft JDBC Driver para SQL Server lesse e descartasse todos os pacotes restantes. Isto pode demorar bastante tempo se a consulta devolver um grande conjunto de dados e, especialmente, se a ligação à rede for lenta.

Diretrizes para a utilização de armazenamento em buffer adaptativo

Os programadores devem seguir estas orientações importantes para minimizar o uso de memória pela aplicação:

  • Evite usar a propriedade de string de ligação selectMethod=cursor para permitir que a aplicação processe um conjunto de resultados muito grande. A funcionalidade de buffering adaptativo permite que as aplicações processem conjuntos de resultados muito grandes, de leitura apenas e sequenciais, sem utilizar um cursor de servidor. Note que quando define selectMethod=cursor, todos os conjuntos de resultados apenas de avanço e de leitura produzidos por essa conexão são afetados. Por outras palavras, se a sua aplicação processar rotineiramente conjuntos curtos de resultados com algumas linhas, criar, ler e fechar um cursor de servidor para cada conjunto de resultados consumirá mais recursos tanto do lado do cliente como do lado do servidor do que no caso em que o selectMethod não está definido para o cursor.

  • Leia valores grandes de texto ou binários como fluxos usando os métodos getAsciiStream, getBinaryStream ou getCharacterStream em vez dos métodos getBlob ou getClop. A partir da versão 1.2, a classe SQLServerCallableStatement fornece novos métodos get<>Type Stream para este propósito.

  • Certifique-se de que as colunas com valores potencialmente grandes estão colocadas em último lugar na lista de colunas numa instrução SELECT e que os métodos get<>Type Stream do SQLServerResultSet são usados para aceder às colunas pela ordem em que foram selecionadas.

  • Garantir que os parâmetros OUT com valores potencialmente grandes sejam declarados em último lugar na lista de parâmetros do SQL usado para criar a SQLServerCallableStatement. Além disso, certifique-se de que os métodos get<>Type Stream do SQLServerCallableStatement são usados para aceder aos parâmetros OUT pela ordem em que são declarados.

  • Evite executar mais do que uma declaração na mesma conexão simultaneamente. Executar outra instrução antes de processar os resultados da instrução anterior pode fazer com que os resultados não processados sejam armazenados na memória da aplicação.

  • Existem alguns casos em que usar selectMethod=cursor em vez de responseBuffering=adaptive seria mais benéfico, tais como:

    • Se a sua aplicação processar lentamente um conjunto de resultados apenas avançado, apenas leitura, como ler cada linha após uma entrada do utilizador, usar selectMethod=cursor em vez de responseBuffering=adaptive pode ajudar a reduzir o uso de recursos pelo SQL Server.

    • Se a sua aplicação processar dois ou mais conjuntos de resultados apenas avançados, apenas de leitura, ao mesmo tempo na mesma ligação, usar selectMethod=cursor em vez de responseBuffering=adaptive pode ajudar a reduzir a memória necessária pelo driver durante o processamento destes conjuntos de resultados.

    Em ambos os casos, tens de considerar a sobrecarga de criar, ler e fechar os cursores do servidor.

Além disso, a lista seguinte apresenta algumas recomendações para conjuntos de resultados atualizáveis com possibilidade de deslocação e que apenas podem ser atualizados sequencialmente:

  • Para conjuntos de resultados deslocáveis, ao buscar um bloco de linhas, o driver lê sempre na memória o número de linhas indicado pelo método getFetchSize do objeto SQLServerResultSet , mesmo quando o buffering adaptativo está ativado. Se o scrolling causar um OutOfMemoryError, pode reduzir o número de linhas recolhidas chamando o método setFetchSize do objeto SQLServerResultSet para definir o tamanho da recolha para um número menor de linhas, até 1 linha, se necessário. Se isto não previne um OutOfMemoryError, evite incluir colunas muito grandes em conjuntos de resultados deslocáveis.

  • Para conjuntos de resultados atualizáveis apenas para frente, ao buscar um bloco de linhas, o driver normalmente lê na memória o número de linhas indicado pelo método getFetchSize do objeto SQLServerResultSet , mesmo quando o buffering adaptativo está ativado na ligação. Se chamar o próximo método do objeto SQLServerResultSet resultar num OutOfMemoryError, pode reduzir o número de linhas obtidas chamando o método setFetchSize do objeto SQLServerResultSet para definir o tamanho da busca para um número menor de linhas, até até 1 linha, se necessário. Também pode forçar o driver a não armazenar linhas em buffer chamando o método setResponseBuffering do objeto SQLServerStatement com o parâmetro "adaptive" antes de executar a sentença. Como o conjunto de resultados não é deslocável, se a aplicação aceder a um valor de coluna grande usando um dos métodos get<Type>Stream, o driver descarta o valor assim que a aplicação o lê, tal como acontece com os conjuntos de resultados apenas leitura em frente.

Consulte também

Melhorar o desempenho e a confiabilidade com o driver JDBC