Usuário com melhor resposta
[RESOLVIDO] Data mais próxima de uma data informada

Pergunta
-
Boa tarde senhores,
Implementei o código abaixo e gostaria de saber se é a melhor forma de se forma, pois está demorando muito. Estou usando linq sql para buscar as informações.
public MedicaoDado retornaMedicoesPorDataProxima(int codigo, DateTime dataInformada) { MedicaoDado medicaoResult = new MedicaoDado(); var medicaoAnterior = (from m in entities.MedicaoDado where m.med_res_id == codigo && m.med_data_medicao <= dataInformada orderby m.med_data_medicao descending select m).FirstOrDefault(); var medicaoPosterior = (from m in entities.MedicaoDado where m.med_res_id == codigo && m.med_data_medicao >= dataInformada orderby m.med_data_medicao ascending select m).FirstOrDefault(); //Se nenhuma das duas data NÃO forem null, é feita a verificação para saber quem é a mais próxima da data informada if (medicaoAnterior != null && medicaoPosterior != null) { int diferencaDtAnterior = Math.Abs(((TimeSpan)(medicaoAnterior.med_data_medicao - dataInformada)).Days); int diferencaDtPosterior = Math.Abs(((TimeSpan)(medicaoPosterior.med_data_medicao - dataInformada)).Days); if (diferencaDtAnterior <= diferencaDtPosterior) { medicaoResult = medicaoAnterior; } else { medicaoResult = medicaoPosterior; } } else { //Se nenhuma das duas data FOREM null, é feita a verificação para saber quem é a mais próxima da data informada if (medicaoAnterior == null && medicaoPosterior == null) { //Não possui dados } else { //Se a data posterior a data informada for null, pega-se a data anterior a data informada if (medicaoPosterior == null) { medicaoResult = medicaoAnterior; } //Se a data anterior a data informada for null, pega-se a data posterior a data informada else { medicaoResult = medicaoPosterior; } } } return medicaoResult; }
- Editado Rafael Rodriguess sexta-feira, 27 de dezembro de 2013 18:09 alt
Respostas
-
Deleted
- Marcado como Resposta Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 18:17
segunda-feira, 23 de dezembro de 2013 22:23 -
Rafael,
Este é um fórum dedicado a tirar dúvidas de SQL Server. Fiz algumas modificações nas suas queries para adequá-las à sintaxe do SQL Server e gostaria que todos os testes fossem feitos com base nelas. Se houver qualquer outro problema e que porventura possa estar relacionado a LinQ, EF ou acesso à dados, solicito que você poste no fórum de LinQ.
select max(med_data_medicao) from MedicaoDado where med_res_id = Código and med_data_medicao <= DataInformada select min(med_data_medicao) from MedicaoDado where med_res_id = Código and med_data_medicao >= DataInformada
Agora, as perguntas que o José.Diz lhe fez:
- há índice cuja primeira (ou única) coluna seja a coluna med_data_medicao?
- há índice cuja primeira (ou única) coluna seja a coluna med_res_id?Eu acrescento:
- Você já verificou o plano de execução da sua query no SQL Server?
- Existe um índice com os campos med_res_id e med_data_medicao?
Para verificar quais índices existem na sua tabela, faça o seguinte:
Abra o SSMS, clique em New Query, escreva:
USE NomedaSuaBase GO -- Clique em <F5> -- escreva o nome da sua tabela: MedicaoDado
Marque o nome todo da sua tabela com o mouse e clique em <ALT><F1>. Vai aparecer diversas informações sobre a sua tabela, um dos resultados que surgirá inicia com "index name" e terá na coluna "index Keys" os campos que fazem parte deste índice. Verifique se há um índice com as colunas citadas.
Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008
- Sugerido como Resposta Edinaldo Junior quinta-feira, 26 de dezembro de 2013 17:55
- Marcado como Resposta Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 18:16
-
Rafael,
Em poucas palavras, o índice faz exatamente o que um índice faz em um livro. Quando você quer determinado assunto, vai até o índice e ele indica em qual página do livro está a sua informação.
Entretanto, estaríamos saindo fora do tema da sua thread. Se você deseja mais informações, abra uma nova pergunta no fórum.
Eu sugiro a você que procure no site da Microsoft sobre a iniciativa MVA, que são treinamentos gratuitos de diversas ferramentas. SEgue o link do MVA de SQL Server: http://www.microsoftvirtualacademy.com/product-training/product-sql-server-pt#?fbid=KUWXv_zdYPN
Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008
- Marcado como Resposta Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 18:16
Todas as Respostas
-
-
A tabela atualmente tem quase 114 mil registros e está demorando em média 50 segundos para fazer as comparações de data. Desculpe a ignorância amigo, mas não entendi o que quis dizer com índices das colunas med_data_medicao e med_res_id.
Não sei se isso pode auxiliar em alguma coisa, mas o método que chama retornaMedicoesPorDataProxima é:
public void BuscaMedicoes() { List<Reservatorio> reservatorios = new List<Reservatorio>(); List<MedicaoDado> medicoes = new List<MedicaoDado>(); reservatorios.AddRange(reservatorioRepositorio.buscarTodosReservatorios()); foreach (var r in reservatorios) { //Agora é buscar as medições de cada reservatório que se aproxima da data informada medicao = medicaoRepositorio.retornaMedicoesPorDataProxima(r.res_id, data); if (medicao.med_id != 0) { medicoes.Add(medicao); } } }
-
Se ta fazendo com Linq to SQL Classes ou Entity Framework ?
Outra coisa ... a Lentidão está no processo está na quantidade de registros + BuscaMedicoes(), esse código precisa ser refatorado.
Se eu tivesse essa tabela eu poderia testá-la pra você e os indices que o nosso amigo disse é de extrema importância para aumentar a performace desses leitura desses registros ...
Se pude dispor a tabela e podendo ser dados fictícios a gente pode testar!
Me fala a camada que utiliza e a regra de negócio! + SQL Create Table da tabela + dados fictícios ...
-
Rafael,
Este é um fórum dedicado a tirar dúvidas de SQL Server. Fiz algumas modificações nas suas queries para adequá-las à sintaxe do SQL Server e gostaria que todos os testes fossem feitos com base nelas. Se houver qualquer outro problema e que porventura possa estar relacionado a LinQ, EF ou acesso à dados, solicito que você poste no fórum de LinQ.
select max(med_data_medicao) from MedicaoDado where med_res_id = Código and med_data_medicao <= DataInformada select min(med_data_medicao) from MedicaoDado where med_res_id = Código and med_data_medicao >= DataInformada
Agora, as perguntas que o José.Diz lhe fez:
- há índice cuja primeira (ou única) coluna seja a coluna med_data_medicao?
- há índice cuja primeira (ou única) coluna seja a coluna med_res_id?Eu acrescento:
- Você já verificou o plano de execução da sua query no SQL Server?
- Existe um índice com os campos med_res_id e med_data_medicao?
Para verificar quais índices existem na sua tabela, faça o seguinte:
Abra o SSMS, clique em New Query, escreva:
USE NomedaSuaBase GO -- Clique em <F5> -- escreva o nome da sua tabela: MedicaoDado
Marque o nome todo da sua tabela com o mouse e clique em <ALT><F1>. Vai aparecer diversas informações sobre a sua tabela, um dos resultados que surgirá inicia com "index name" e terá na coluna "index Keys" os campos que fazem parte deste índice. Verifique se há um índice com as colunas citadas.
Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008
- Sugerido como Resposta Edinaldo Junior quinta-feira, 26 de dezembro de 2013 17:55
- Marcado como Resposta Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 18:16
-
Realmente fiz a verificação amigo e não existe índice com os campos med_res_id e med_data_medicao.
A tabela já possui um indice clusterizado que é o indice da tabela med_id.
Como ficaria com a criação desses índices?
- Editado Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 17:40 alt
-
Incrível!
Apenas criei os índices para as colunas que vocês me sugeriram e reduzi o tempo de pesquisa de 50 segundos para 15 segundos.
Agora alguém poderia me dar uma explicação na prática o que acontece para que a pesquisa fique otimizada dessa forma?
-
Rafael,
Em poucas palavras, o índice faz exatamente o que um índice faz em um livro. Quando você quer determinado assunto, vai até o índice e ele indica em qual página do livro está a sua informação.
Entretanto, estaríamos saindo fora do tema da sua thread. Se você deseja mais informações, abra uma nova pergunta no fórum.
Eu sugiro a você que procure no site da Microsoft sobre a iniciativa MVA, que são treinamentos gratuitos de diversas ferramentas. SEgue o link do MVA de SQL Server: http://www.microsoftvirtualacademy.com/product-training/product-sql-server-pt#?fbid=KUWXv_zdYPN
Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008
- Marcado como Resposta Rafael Rodriguess quinta-feira, 26 de dezembro de 2013 18:16
-
-
Amigo,
Fiz uns testes e pesquisas aqui e a melhor solução é utilizando o FirstOrDefault(), pois ele pega um único registro e se não houver nada ele traz vazio. Tentei utilizar o TAKE(1), que seria equivalente ao TOP 1, mas não é uma boa ideia, pois apesar de retornar um único registro ele vem em um IEnumerable<string>.
Ao invés de colocar um único índice com as duas colunas (med_res_id e med_data_medicao), coloquei um índice para e minha consulta que estava com 15 segundos (que já estava boa!!!) foi para 6 segundos (que agora está fantástico!!!).
No geral o resultado foi excelente! Eu estava com uma pesquisa que demorava 50 segundos que foi reduzida para 6 segundos.
Se ninguém tiver mais nada que acrescentar finalizarei a Thread.
Obrigado a todos que me ajudaram!!!!!!!!