none
Limite de Registros num Dataset RRS feed

  • Pergunta

  • Boa tarde,

    Sou aquilo que poderíamos chamar de um programador curioso avançado. rsrsrs

    Aconteceu que me pediram para fazer uma limpeza numa tabela no SQL Server. A solução (algoritmo) que encontrei foi armazenando toda a tabela num dataset e depois fazendo uma leitura registro a registro do dataset para aí sim aplicar as correções.

    Funcionaou perfeitamente com 200 registros. Mas, quando fui testar na tabela original, travou de deu timeout na hora de montar o select, pois a tabela possui a significativa quantidade de 6 milhoes de registros.

    Alguém poderia me ajudar com alguma ideia?

    Obrigado

    Pestana

    sexta-feira, 1 de julho de 2016 18:14

Respostas

  • Beto,

    Será que o uso de Views ou CTEs não poderia ser uma forma de trazer a quantidade desejada de registros?

    Ou até mesmo pensar em criar uma procedure passando os dados desejados para posteriormente filtras estes dados e retorna um conjunto menor de linhas.


    Pedro Antonio Galvao Junior [MVP | MCC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | Professor Universitario | SoroCodigos | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 4 de julho de 2016 00:29

Todas as Respostas

  • Oi Beto.

    Poderia postar a query para ter uma ideia melhor do que está fazendo?

    Obrigado!

    sexta-feira, 1 de julho de 2016 18:18
  • Então,

    Possuo uma tabela com milhoes de registros e inseridos cerca de 12 registros dentro do mesmo minuto na coluna timestamp. Fiz uma aplicação para ler todos os registros e trata-los após a mudança de minuto. Após esse tratamento eu insiro numa nova tabela um único registro referente a esse minuto tratado. O resultado é dar uma limpeza na tabela reduzindo bastante o número de registros.

    Tudo funciona perfeitamente quando faço testes em tabelas com 200 ou 300 registros. Mas quando testo na tabela oficial com milhoes de registros já trava nessa primeira consulta (a baixo), à tabela quando carrego os registros existentes.

    public DataSet datasDif(string Tabela, string Coluna)
            {
                SqlDataAdapter da = new SqlDataAdapter("select distinct(" + Coluna + ") from " + Tabela, con);
                con.Open();
    
                try
                {
                    DataSet ds = new DataSet();
                    da.Fill(ds);
                    return ds;
                }
                finally
                {
                    con.Close();
                }
            }

    Como me anunciei, sou um curioso avaçado e certamente devo ter pensado como "criança". rsrsrs

    Help me!

    Obrigado

    sexta-feira, 1 de julho de 2016 18:39
  • Ok!

    Você não poderia realizar essa operação diretamente no banco?

    Uma opção em que pensei seria você dividir esse processamento em blocos, tipo de 200 em 200 registros com OFFSET e FETCH.

    No exemplo abaixo, tenho uma tabela com 10 registros e vou executar um select de 2 em 2 registros.

    Você poderia seguir essa mesma lógica.

    DECLARE @TABELA TABLE
    (
    valor int
    );
    
    INSERT INTO @TABELA
    VALUES
    (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
    
    
    DECLARE @TOTAL_REGISTROS INT;
    DECLARE @INTERVALO INT;
    DECLARE @INICIO INT;
    
    SET @INTERVALO = 2;
    
    SET @INICIO = 0;
    
    SELECT @TOTAL_REGISTROS = COUNT(*) FROM @TABELA;
    
    WHILE @INICIO < @TOTAL_REGISTROS 
    BEGIN
    	SELECT * FROM @TABELA
    	ORDER BY VALOR
    	OFFSET @INICIO ROWS FETCH NEXT @INTERVALO ROWS ONLY;
    	SET @INICIO = @INICIO + @INTERVALO;
    END

    • Sugerido como Resposta Edvaldo A sexta-feira, 1 de julho de 2016 19:02
    sexta-feira, 1 de julho de 2016 19:00
  • Mas como eu passaria isso no meu Dataset, pois preciso de uma lista com todos os registros para poder tratá-los devidamente e gerar uma nova tabela já organizada.

    Andei lendo a respeito de fragmentar uma consulta usando SKIP e TAKE. Procede?

    sábado, 2 de julho de 2016 04:17
  • Olá Edvaldo, deixa eu dar uma organizada no problema:

    Acabei optando em criar novas tabelas limitando os registros trabalhados na tabela original montando meu Dataset da seguinte forma:

    public DataSet dadosALL(string Banco, string Tabela, string Coluna, string colunasSelect)
            {
                SqlDataAdapter da = new SqlDataAdapter("select TOP 200000 " + colunasSelect + " from [" + Banco + "].[dbo].[" + Tabela + "]", con);
                con.Open();
    
                try
                {
                    DataSet ds = new DataSet();
                    da.Fill(ds);
                    return ds;
                }
                finally
                {
                    con.Close();
                }
            }

    Dessa forma parei de ter problemas no select que antes eu tinha, já que minha tabela possui 58 milhoes de registros com 5.02 GB. Porém dessa forma eu tenho que deletar os registros já utilizados na tabela original para que eu faça um novo select de 200000 registros para mais uma nova tabela já organizada. Acontece que na hora do delete, a query acaba dando "timeout" provavelmente pelo mesmo problema já que a query deverá correr a tabela inteira.

    Alguma ideia para essa solução?

    Obrigado

    Pestana

    domingo, 3 de julho de 2016 17:12
  • Beto,

    Será que o uso de Views ou CTEs não poderia ser uma forma de trazer a quantidade desejada de registros?

    Ou até mesmo pensar em criar uma procedure passando os dados desejados para posteriormente filtras estes dados e retorna um conjunto menor de linhas.


    Pedro Antonio Galvao Junior [MVP | MCC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | Professor Universitario | SoroCodigos | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 4 de julho de 2016 00:29
  • Obrigado Pedro,

    Resolvido.

    segunda-feira, 11 de julho de 2016 17:05