Very slow query to export in excel

Asked

Viewed 81 times

0

I created a method to export a few columns to xls and it is very slow the process, it takes about one minute to do the whole process.

    public void Download(string datainicio, string datafinal, int? searchContrato, string searchCliente, string tipo, string status)
    {
        DateTime dt1 = Convert.ToDateTime(datainicio);
        DateTime dt2 = Convert.ToDateTime(datafinal);

        var tbl_caminhos = db.tbl_caminho_backup.AsNoTracking().Where(x => x.ativo == true && x.tbl_cliente_verusbackuponline.ativo == true).ToList();
        var tbl_logs = db.vw_logs_backuponline.AsNoTracking().Where(x => DbFunctions.TruncateTime(x.data_inicio) >= DbFunctions.TruncateTime(dt1) && DbFunctions.TruncateTime(x.data_inicio) <= DbFunctions.TruncateTime(dt2)).ToList();

        //List<vw_logs_backuponline> tbl_logs = null;
        if (!String.IsNullOrEmpty(tipo))
        {
            tbl_caminhos = tbl_caminhos.Where(x => x.tipo == tipo).ToList();

            tbl_logs = tbl_logs.Where(s => s.log_tipo == tipo).ToList();
        }
        if (!String.IsNullOrEmpty(searchCliente))
        {
            tbl_caminhos = tbl_caminhos.Where(x => x.tbl_cliente_verusbackuponline.nome_razao.ToLower().Contains(searchCliente.ToLower())).ToList();
            tbl_logs = tbl_logs.Where(s => s.nome_razao.ToLower().Contains(searchCliente.ToLower())).ToList();
        }
        if (searchContrato != null)
        {
            tbl_caminhos = tbl_caminhos.Where(x => x.tbl_cliente_verusbackuponline.contrato == searchContrato).ToList();

            tbl_logs = tbl_logs.Where(s => s.contrato == searchContrato).ToList();
        }
        if (!String.IsNullOrEmpty(status) && status == "0")
        {
            tbl_caminhos = tbl_caminhos.Where(x => !tbl_logs.Select(l => l.id_caminho_backup).Contains(x.id_caminho_backup)).ToList();

            tbl_logs = tbl_logs.Where(s => s.data_fim != null).ToList();
        }
        if (!String.IsNullOrEmpty(status) && status == "1")
        {
            tbl_caminhos = null;
            tbl_logs = tbl_logs.Where(s => s.data_fim != null).ToList();
        }

        if (tbl_caminhos != null)
        {
            for (DateTime dtRef = dt1; dtRef <= dt2; dtRef = dtRef.AddDays(1))
            {
                //aqui pego todos os caminhos cadastrados para os clientes
                foreach (var caminhos in tbl_caminhos)
                {
                    //verifico se existe um log para o caminho, se tiver eu sei que foi realizado o backup
                    if (tbl_logs.Where(x => x.id_caminho_backup == caminhos.id_caminho_backup && (x.data_inicio >= dtRef && x.data_inicio <= dtRef)).Count() <= 0)
                    {
                        //se entrou aqui é pq não existe um log para o caminho, então crio uma linha de falha do backup
                        vw_logs_backuponline log = new vw_logs_backuponline();
                        log.contrato = caminhos.tbl_cliente_verusbackuponline.contrato;
                        log.nome_razao = caminhos.tbl_cliente_verusbackuponline.nome_razao;
                        log.cidade = caminhos.tbl_cliente_verusbackuponline.cidade;
                        log.log_tipo = caminhos.tipo;
                        log.data_inicio = dtRef;
                        log.hora_inicio = caminhos.tbl_cliente_verusbackuponline.hora_backup;
                        log.bucket = caminhos.tbl_cliente_verusbackuponline.bucket;
                        log.hora_backup = caminhos.tbl_cliente_verusbackuponline.hora_backup;
                        log.msg_operacao = "<span class='glyphicon glyphicon-alert' aria-hidden='true'></span>";
                        log.caminho_ativo = true;

                        tbl_logs.Add(log);
                    }
                }
            }
            //aqui removo os com sucesso quando a busca é apenas os com falhas
            if (!String.IsNullOrEmpty(status) && status == "0")
            {
                tbl_logs.RemoveAll(x => x.data_fim != null);
            }

        }
        var logs = tbl_logs.Select(x => new LogsBackup() { Contrato = x.contrato, Modalidade = x.log_tipo, Cidade = x.cidade, UF = x.uf, Nome_Razao = x.nome_razao, Dias_Backup = (x.data_inicio - x.data_fim).ToString().FirstOrDefault().ToString() }).AsQueryable().ToList();

        try
        {
            GridView gridView = new GridView();

            gridView.DataSource = logs;
            gridView.DataBind();

            Response.ClearContent();
            Response.Buffer = true;
            Response.AddHeader("content-disposition", "attachment;filename=" + datafinal + "VerusBackup.xls");
            Response.ContentType = "application/vnd.ms-excel";
            Response.Charset = "";

            using (StringWriter stringWriter = new StringWriter())
            {
                using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
                {

                    gridView.RenderControl(htmlTextWriter);
                    Response.Output.Write(stringWriter.ToString());
                    Response.Flush();
                    Response.End();
                }
            }
        }
        catch (Exception ex)
        {

            throw ex;
        }

    }

Script na View:

  $("#btnExportar").click(function (e) {
    var datainicio = $('#datainicio').val();
    var datafinal = $('#datafinal').val();
    var searchContrato = $('#searchContrato').val();
    var tipo = $('#tipo').val();
    var status = $('#status').val();
    $.ajax({
        type: 'GET',
        url: "@Url.Action("Download", "logsbackuponline")",
        data: { datainicio: datainicio, datafinal: datafinal, searchContrato: searchContrato, tipo: tipo, status: status },
        async: true,
        success: function (Result) {
            window.location = '/logsbackuponline/Download?datainicio=' + datainicio + '&datafinal=' + datafinal + '&searchContrato=' + searchContrato + '&tipo=' + tipo + '&status=' + status;
        }
    })        
}); 
  • 1

    what have you analyzed? already used the Diagnostic tools to identify where the slowness is?

  • I didn’t even use the tool, it is noticeable the slowness when clicking the button to export.

  • Performance problems rarely go by themselves. To begin with, I think it would be interesting for you to first identify if the problem is in the request, in the processing of the backend (and if this is the case which block is what is causing the delay and needs to be optimized) or in the upload of the generated file. Right away I’m seeing a lot of ToList expendable in code and I really don’t know what you intend with this excerpt (x.data_inicio - x.data_fim).ToString().FirstOrDefault().ToString().

  • 1

    Hadrian, "by clicking the button" Makes me think of a black box. You click and it is slow is a user comment that, you need to look at the code and inspect to see where it is slow.. in the return of the bank? no foreach, generating the file, in the same download? if you use the Diagnostic tools for example, you will see where you are slower, then you can analyze exactly this point, otherwise it is difficult to help you

  • @Ricardopunctual is in the query to DB, when I did this query the answer was momentary, but when I changed to the example above, the answer takes 00:00:56 seconds. var tbl_logs = db.vw_logs_backuponline.Select(x => { x.raz_name, x.city, x.Uf, x.log_type})Asnotracking(). Where(x => DbFunctions.TruncateTime(x.data_inicio) >= DbFunctions.TruncateTime(dt1) && DbFunctions.TruncateTime(x.data_inicio) <= DbFunctions.TruncateTime(dt2));

  • very good Adriano, now it would be nice to see the query generated to analyze what may be causing slowness, until analyzing the execution plan. Can you capture the query? If you do not know, you have this question that explains how to do: https://answall.com/questions/21398/como-saber-qual-sql-%C3%A9-generated-by-Orm-Entity-framework

  • So, this is the code below in the link, the slowness occurs well at 39, and the select is this: https://pastebin.com/FYHZ8Zjf Current code: https://pastebin.com/Ud6wzLFL

  • *The slowness occurs right on line 39 (where the data returns from a view), and the select is this: https://pastebin.com/FYHZ8Zjf Current code: https://pastebin.com/Ud6wzLFL

Show 3 more comments

1 answer

3

Early on you can take out all these ToList() and run the query only at the end. Example:

var tbl_caminhos = db.tbl_caminho_backup.AsNoTracking().Where(x => x.ativo && x.tbl_cliente_verusbackuponline.ativo);


if (!String.IsNullOrEmpty(tipo))
{
    tbl_caminhos = tbl_caminhos.Where(x => x.tipo == tipo);
}


var caminhos = tbl_caminhos.ToList();

So the query is executed only once, at the end when all filters are applied.

After that, we can analyze amount of records, or other factors that may be causing slowness

ps. no need to compare a bool field to true, ativo == true, ativo will already return true or false

Browser other questions tagged

You are not signed in. Login or sign up in order to post.