Neste artigo, ilustramos como usar o recurso OFFSET FETCH como uma solução para carregar grandes volumes de dados de uma base de dados relacional usando uma máquina com memória limitada e evitando uma exceção fora da memória. Descrevemos como carregar dados em lotes para evitar colocar uma grande quantidade de dados na memória.

Este artigo é o primeiro da série Dicas e Truques SSIS que visa ilustrar algumas melhores práticas.

Introdução

Ao pesquisar online por problemas relacionados à importação de dados SSIS, você encontrará soluções que podem ser usadas em ambientes ótimos ou tutoriais para lidar com uma pequena quantidade de dados. Infelizmente, estas soluções revelam-se inadequadas num ambiente real.

Na realidade, as empresas mais pequenas nem sempre podem adoptar novos equipamentos de armazenamento, processamento e tecnologias, embora ainda tenham de lidar com uma quantidade crescente de dados. Isto é especialmente verdade para a análise das mídias sociais, pois elas devem analisar o comportamento de seu público-alvo (clientes).

Da mesma forma, nem todas as empresas podem carregar seus dados na nuvem devido ao alto custo, juntamente com questões de privacidade e confidencialidade dos dados.

OFFSET FETCH feature

OFFSET FETCH é uma funcionalidade adicionada à cláusula ORDER BY, que começa com a edição 2012 do SQL Server. Ele pode ser usado para extrair um número específico de linhas a partir de um índice específico. Como exemplo, temos uma consulta que retorna 40 linhas e precisamos extrair 10 linhas a partir da 10ª linha:

1
2
3
4
5

SELECCIONAR *
FROM Tabela
ORDEM POR ID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS APENAS

Na consulta acima, OFFSET 10 é usado para saltar 10 linhas e FETCH 10 ROWS APENAS é usado para extrair apenas 10 linhas.

Para obter informações adicionais sobre a cláusula ORDER BY e a funcionalidade OFFSET FETCH, consulte a documentação oficial: Usando OFFSET e FETCH para limitar as linhas retornadas.

Usando OFFSET FETCH para carregar dados em pedaços (paginação)

Uma das principais finalidades de usar a funcionalidade OFFSET FETCH é carregar dados em pedaços. Imaginemos que temos uma aplicação que executa uma consulta SQL e precisa de mostrar os resultados em várias páginas onde cada página contém apenas 10 resultados (semelhante ao motor de busca do Google).

A seguinte consulta pode ser usada como uma consulta de paginação onde @PageSize é o número de linhas que você precisa mostrar em cada trecho e @PageNumber é o número de iteração (página):

1
2
3
4
5

SELECT <algumas colunas>
DE < nome da tabela>
ORDEM POR <algumas colunas>
OFFSET @PageSize * @PageNumber ROWS
FETCH NEXT @PageSize ROWS ONLY;

Este artigo não pretende ilustrar todos os casos de uso do recurso OFFSET FETCH, nem discutir as melhores práticas. Existem muitos artigos online que pode consultar para mais informações:

  • Paginação com OFFSET / FETCH : Uma maneira melhor
  • Paginação no SQL Server usando OFFSET / FETCH

Implementar a funcionalidade OFFSET FETCH dentro do SSIS para carregar um grande volume de dados em pedaços

Muitas vezes foi-nos pedido para construir um pacote SSIS que carrega uma enorme quantidade de dados do SQL Server com recursos limitados da máquina. Carregar dados usando OLE DB Source usando o modo Table ou View data access estava causando uma exceção à memória.

Uma das soluções mais fáceis é usar a função OFFSET FETCH para carregar dados em pedaços para evitar erros de falta de memória. Nesta seção, nós fornecemos um guia passo a passo sobre a implementação desta lógica dentro de um pacote SSIS.

Primeiro, devemos criar um novo pacote de Serviços de Integração, depois declarar quatro variáveis como segue:

  • RowCount (Int32): Armazena o número total de linhas na tabela de origem
  • IncrementValue (Int32): Armazena o número de linhas que precisamos especificar na cláusula OFFSET (similar a @PageSize * @PageNumber no exemplo acima)
  • RowsInChunk (Int32): Especifica o número de linhas em cada pedaço de dados (similar a @PageSize no exemplo acima)
  • SourceQuery (String): Armazena o comando SQL de origem usado para buscar dados

Após declarar as variáveis, nós atribuímos um valor padrão para a variável RowsInChunk; neste exemplo, nós a configuraremos para 1000. Além disso, devemos definir a expressão Source Query, como segue:

1
2
3
4
5

“SELECT *
> FROM …
ENCOMENDAR POR
OFFSET ” + (DT_WSTR,50)@ + ” LINHAS
BUSCAR A SEGUIR ” + (DT_WSTR,50) @ + ” ROWS ONLY”

Figura 1 – Adicionando variáveis

A seguir, adicionamos uma Tarefa Executar SQL para obter o número total de linhas na tabela de origem. Neste exemplo, usamos a tabela Person armazenada na base de dados AdventureWorks2017. Na tarefa Execute SQL, usamos a seguinte instrução SQL:

1
SELECT COUNT(*) FROM …

>

Figura 2 – Configuração da Tarefa Executar SQL

E, devemos alterar a propriedade Definir Resultado para Fila Única. Em seguida, na aba Result Set, selecionamos a variável RowCount para armazenar o resultado definido como mostrado na imagem abaixo:

Figura 3 – Mapeamento do resultado definido como variável

Após configurar a Tarefa Execute SQL, adicionamos um For Loop Container, com as seguintes especificações:

  • InitExpression: @IncrementValue = 0
  • EvalExpression: @IncrementValue <= @RowCount
  • AssignExpression: @IncrementValue = @IncrementValue + @RowsInChunk

Figura 4 – Configurando para container de loop

Após configurar o For Loop Container, adicionamos uma tarefa de fluxo de dados dentro dele. Então, dentro da tarefa de fluxo de dados, adicionamos uma Fonte OLE DB e Destino OLE DB.

Na Fonte OLE DB selecionamos o comando SQL do modo de acesso a dados variáveis, e selecionamos @User::SourceQuery variável como a fonte.

Figura 5 – Configuração da fonte OLE DB

Especificamos a tabela de destino dentro do componente OLE DB Destination:

Figura 6 – Tela de tarefa de fluxo de dados

O fluxo de controle de pacotes deve se parecer com o seguinte:

Figura 7 – Tela de controle de fluxo de dados

Limitações

Depois de ilustrar como carregar dados em pedaços usando a função OFFSET FETCH no SSIS, vamos notar que esta lógica tem algumas limitações:

  1. Você sempre precisa de algumas colunas para serem usadas na cláusula ORDER BY (Prefere-se a chave Identity ou Primary), já que OFFSET FETCH é uma característica da cláusula ORDER BY e não pode ser implementada separadamente
  2. Se ocorrer um erro durante o carregamento dos dados, todos os dados exportados para o destino são comprometidos e apenas o pedaço de dados atual é revertido para trás. Isto pode requerer passos adicionais para evitar a duplicação de dados ao executar o pacote novamente

OFFSET FETCH usando outros provedores de banco de dados

Na seção seguinte, nós cobrimos brevemente a sintaxe usada por outros provedores de banco de dados:

Oracle

Com Oracle, você pode usar a mesma sintaxe do SQL Server. Consulte o seguinte link para obter mais informações: Oracle FETCH

SQLite

Em SQLite, a sintaxe é diferente da do SQL Server, já que você usa o recurso LIMIT OFFSET, como mencionado abaixo:

1
2
3

SELECCIONAR * DO MYTABLE ORDEM POR ID_COLUME
LIMIT 50
OFFSET 10

MySQL

No MySQL, a sintaxe é semelhante ao SQLite, uma vez que se utiliza o LIMIT OFFSET em vez do OFFSET Fetch.

DB2

No DB2, a sintaxe é semelhante à do SQLite, uma vez que utiliza o LIMIT OFFSET em vez do OFFSET FETCH.

Conclusion

Neste artigo, descrevemos a funcionalidade OFFSET FETCH encontrada no SQL Server 2012 e superiores. Ilustramos como usar este recurso para criar uma consulta de paging, depois fornecemos um guia passo a passo sobre como carregar dados em pedaços para permitir extrair grandes quantidades de dados usando uma máquina com recursos limitados. Finalmente, mencionamos algumas das limitações e diferenças de sintaxe com outros provedores de banco de dados.

  • Autor
  • Recent Posts
Hadi é um profissional do SQL Server com mais de 10 anos de experiência. A sua principal experiência é na integração de dados. Ele é um dos principais colaboradores de ETL e SQL Server Integration Services no Stackoverflow.com . Também publicou várias séries de artigos sobre Biml, características SSIS, motores de busca, Hadoop, e muitas outras tecnologias.
Além de trabalhar com SQL Server, ele trabalhou com diferentes tecnologias de dados como bancos de dados NoSQL, Hadoop, Apache Spark. Ele é um profissional certificado Neo4j e ArangoDB.
No nível acadêmico, Hadi tem dois mestrados em ciência da computação e computação empresarial. Atualmente, ele é candidato a Ph.D. em ciência de dados com foco em técnicas de avaliação de qualidade de Grandes Dados.
Hadi realmente gosta de aprender coisas novas todos os dias e compartilhar seus conhecimentos. Você pode alcançá-lo em seu site pessoal.
Veja todos os posts de Hadi Fadlallah

>Posts mais recentes de Hadi Fadlallah (ver todos)
  • Construir cubos SSAS OLAP usando Biml – 16 de Março, 2021
  • Migração de bases de dados gráficos do SQL Server para o Neo4j – 9 de Março de 2021
  • Começar com a base de dados gráficos do Neo4j – 5 de Fevereiro de 2021

Deixe uma resposta

O seu endereço de email não será publicado.