Array
(
)

Pesquisa em BD muito lenta

Pjava
   - 10 ago 2012

Sei que a forma mais rápida, é trabalhar diretamente no BD, porem, no meu caso não é possível, então apelei para uma aplicação. Meu caso é o seguinte: Numa dada tabela tenho um campo de tamanho 20 posições. As quatro primeiras forma o que chamamos de operacao, uma sequecencia de zeros, que não tem um tmanho exato(variável) e depois uma sequecencia de dígitos. Isso vai para os bancos q meu cliente trabalha. Acontece, que quando vem de um determinado banco(Itau), eles mandam apenas os últimos digitos apos a sequencia de zeros, em uma planilha que varia: Valores com: 6,7,8,9,10,11,12,13,14 dígitos. O meu cliente é leigo e eu não posso mndar um script para eles, para substring com 6,7,8..14 posições, para eles ficarem executando lá. Qdo vou lá eu faço isso e cobro por script, o que eles não querem mais. Aí fiz uma aplicação, mas está lenta demais. Veja o código quase completo(ainda falta o código da geração da planilha final) do aplicativo.
private void Execute()
{
string sql = ;
string temp = ;
string caminho = edtPath.Text;
string[] valor;
int tamanho = 0;
string contrato_temp = ;
string campo = ;
MySqlConnection conn = new MySqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings[conexaoMysql].ConnectionString;
MySqlConnection conn1 = new MySqlConnection();
conn1.ConnectionString = ConfigurationManager.ConnectionStrings[conexaoMysql].ConnectionString;
MySqlCommand cmd = new MySqlCommand();

conn.Open();
conn1.Open();
DataTable tbl = new DataTable();
tbl.Columns.Add(Operacao, typeof(string));
tbl.Columns.Add(Contrato, typeof(string));
tbl.Columns.Add(Data de Vencimento, typeof(DateTime));
tbl.Columns.Add(Empresa, typeof(string));
tbl.Columns.Add(Status, typeof(string));
tbl.Columns.Add(Tipo de Envio, typeof(string));
tbl.Columns.Add(Data de Registro, typeof(DateTime));
tbl.Columns.Add(Data de Postagem, typeof(DateTime));
tbl.Columns.Add(Data de Retorno, typeof(DateTime));

sql = select contrato from temp_baixa_arquivo;
cmd.Connection = conn;
cmd.CommandText = sql;

MySqlDataReader dr = cmd.ExecuteReader();

tamanho = 17999;
int i = 0;
valor = new string[tamanho];
while (dr.Read()& i tamanho)
{
contrato_temp = dr[contrato].ToString();
valor[i] = contrato_temp;
i += 1;
}
//while (dr.Read())
for (int j = 0; j valor.Length; j++ )
{
campo = valor[j].ToString();
sql = select a.campo027 as Operacao,a.contrato, a.campo028 as Data_Contrato, CLS +
,a.dtreg as Data_Registro, a.dtreg as Data_Postagem,b.dtbaixa as Data_Retorno +
,b.TPOCO as Status,a.tipodocumento as Tipo_Envio +
from +
baixas b inner join arquivo a on(a.registro = b.registro) +
where +
a.contrato like % + campo + +
and a.codcli = 60 ;
MySqlCommand cmdTemp = new MySqlCommand();
cmdTemp.Connection = conn1;
cmdTemp.CommandText = sql;
MySqlDataReader drtemp = cmdTemp.ExecuteReader();
while (drtemp.Read())
{
string oper = drtemp[Operacao].ToString();
string contrat = campo;
string dt_contrat = drtemp[Data_Contrato].ToString();
string cls = drtemp[CLS].ToString();
string dt_reg = drtemp[Data_Registro].ToString();
string dt_post = drtemp[Data_Postagem].ToString();
string dt_ret = drtemp[Data_Retorno].ToString();
string status = drtemp[Status].ToString();
string envio = drtemp[Tipo_Envio].ToString();
DataRow lin = tbl.NewRow();
lin[Operacao] = oper;
lin[Contrato] = contrat;
lin[Data de Vencimento] = dt_contrat;
lin[Empresa] = CLS;
lin[Status] = status;
lin[Tipo de Envio] = envio;
lin[Data de Registro] = dt_reg;
lin[Data de Postagem] = dt_post;
lin[Data de Retorno] = dt_ret;
tbl.Rows.Add(lin);
}
drtemp.Dispose();
cmdTemp.Dispose();
}
dr.Dispose();
conn.Close();
} //Fim do Execute

Joel Rodrigues
   - 10 ago 2012

PJava, inicialmente eu gostaria de fazer uma pergunta: por que você está instanciando a DataTable, adicionando as colunas e depois a linhas dentro de um loop? Por que você não a preenche diretamente com o resultado da consulta?
Veja um exemplo:

#Código

//conn é a MySqlConnection
MySqlCommand cmd = new MySqlCommand(´SELECT * FROM Tabela´, conn);
MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
DataTable tab = new DataTable();
conn.Open();
adap.Fill(tab);


Com isso, a tabela estará preenchida com todos os campos e registros da sua consulta.

Faça o teste.

0
|
0

Pjava
   - 10 ago 2012

Eu preciso do loop para a query, porque esse select será realizado, de acordo com o valor de um campo que vem de outra tabela. Então pego esse campo e passa na cláusula like ou na substring. Com o like está muito lento, então passarei com substring, mas aí terei que declarar duas var para ir alimentando a substring, pos esse campo vem com tamanho variável de 7 digitos até 13. E na sub eu tenho que passar substring(campo,de,ate), como varia, eu preciso do loop. Isso é o que eu imagino ser, mas dá para mesclar com o que o Joel me passou.

0
|
0

Pjava
   - 10 ago 2012

Joel, melhorei a consulta e acho que o seu código se encaixa. Não mais preciso de duas tables, mas agora dá esse erro

Uma tentativa de conexão falhou porque o componente conectado não respondeu\r\ncorretamente após um período de tempo ou a conexão estabelecida falhou\r\nporque o host conectado não respondeu}

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

Exatamento na linha:
adap.Fill(tbl);

0
|
0

Pjava
   - 10 ago 2012

Esse é o novo código

private void Execute()
{
string sql = ;
string caminho = @D:\CLS Documentos\Teste\Minha_Planilha.xls;

MySqlConnection conn = new MySqlConnection();
conn.ConnectionString = ConfigurationManager.ConnectionStrings[conexaoMysql].ConnectionString;

conn.Open();

DataTable tbl = new DataTable();
tbl.Columns.Add(Operacao, typeof(string));
tbl.Columns.Add(Contrato, typeof(string));
tbl.Columns.Add(Data_Vencimento, typeof(DateTime));
tbl.Columns.Add(Empresa, typeof(string));
tbl.Columns.Add(Status, typeof(string));
tbl.Columns.Add(Envio, typeof(string));
tbl.Columns.Add(Data_Registro, typeof(DateTime));
tbl.Columns.Add(Data_Postagem, typeof(DateTime));
tbl.Columns.Add(Data_Retorno, typeof(DateTime));

sql = SELECT t1.campo027 as Operacao +
,( SELECT t2.contrato FROM temp_baixa_arquivo AS t2 WHERE t2.contrato = SUBSTRING(t1.contrato, -length(t2.contrato), length(t2.contrato))limit 1) AS Achou +
, t1.campo028 as Data_Contrato, CLS ,t1.dtreg as Data_Registro, t1.dtreg as Data_Postagem,b.dtbaixa as Data_Retorno ,b.TPOCO as Status +
,t1.tipodocumento as Tipo_Envio +
FROM arquivo AS t1 inner join baixas b on t1.registro = b.registro +
where t1.codcli = 60 +
order by achou desc;

//conn é a MySqlConnection
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
adap.Fill(tbl);

using (StreamWriter sw = File.CreateText(caminho))
{
foreach (DataRow dw in tbl.Rows)
{
sw.WriteLine(dw[Operacao].ToString() + \t + dw[Contrato].ToString() + \t + dw[Data_Vencimento].ToString() + \t +
dw[Empresa].ToString() + \t + dw[Status].ToString() + \t + dw[Envio].ToString() + \t + dw[Data_Registro].ToString() + \t +
dw[Data_Postagem].ToString() + \t + dw[Data_Retorno].ToString());
}
}

dgv.DataSource = tbl;

} //Fim do Execute

0
|
0

Pjava
   - 10 ago 2012

Resolvi a questão do time out. Fiz assim:

adap.SelectCommand.CommandTimeout = 360;

0
|
0

Joel Rodrigues
   - 16 ago 2012

Valeu, PJava.
Estou encerrando o tópico.

0
|
0