Performance issue when exporting a large number of records to Excel - is it normal?

10 posts, 0 answers
  1. Kelly
    Kelly avatar
    55 posts
    Member since:
    Nov 2007

    Posted 15 Apr 2009 Link to this post

    I'm getting a performance issue when I try to export my grid to Excel.  The data source has about 67,000 records and the filtered result set has about 12,000 records.  Is it normal for the Excel export to run for 20 minutes without showing any results when there are that many records?  Is there anything in my code that I could tweak to avoid this issue?

    1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PinList.aspx.cs" Inherits="PinList" 
    2     MasterPageFile="~/Admin/Masterpages/AdminPageWithMenu.master" Theme="MillenniumAdmin" 
    3     Title="PIN List" %> 
    4  
    5 <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %> 
    6 <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">  
    7  
    8     <script type="text/javascript">  
    9         function OpenRadWindowCreateNewPins()  
    10         {  
    11              var oWindow = radopen("Popups/NewPIN.aspx", null);  
    12              oWindow.op  
    13              oWindow.SetSize(600, 520);  
    14         }  
    15          
    16        //Reloads PIN Grid   
    17        function OnClientClose(radWindow)  
    18        {  
    19             location.reload();  
    20        }  
    21     </script> 
    22  
    23 </asp:Content> 
    24 <asp:Content ID="Content2" ContentPlaceHolderID="PageTitle" runat="Server">  
    25     PIN List  
    26 </asp:Content> 
    27 <asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">  
    28     <telerik:RadWindowManager ID="winMgr" Skin="Outlook" Behaviors="Close, Move, Resize" 
    29         Modal="true" VisibleStatusbar="false" runat="server" Width="520px" Height="450px" 
    30         OnClientClose="OnClientClose">  
    31     </telerik:RadWindowManager> 
    32     <asp:Label ID="Message" runat="server" EnableViewState="false"></asp:Label> 
    33     <telerik:RadGrid ID="PinGrid" runat="server" AutoGenerateColumns="false" AllowAutomaticDeletes="false" 
    34         AllowAutomaticInserts="false" AllowAutomaticUpdates="false" ShowStatusBar="true" 
    35         AllowMultiRowSelection="false" AllowPaging="true" PageSize="30" OnNeedDataSource="PinGrid_NeedDataSource" 
    36         OnItemCreated="PinGrid_ItemCreated" AllowFilteringByColumn="true" OnPreRender="PinGrid_PreRender" 
    37         OnItemCommand="PinGrid_ItemCommand" Width="90%">  
    38         <ExportSettings> 
    39             <Excel Format="ExcelML" /> 
    40         </ExportSettings> 
    41         <MasterTableView AllowNaturalSort="false" CommandItemDisplay="Top" DataKeyNames="PINID" 
    42             AutoGenerateColumns="false" AllowSorting="true">  
    43             <PagerStyle Mode="NextPrevAndNumeric"></PagerStyle> 
    44             <CommandItemTemplate> 
    45                 <asp:LinkButton ID="lnlRebind" runat="server" OnClientClick="javascript:location.reload()" 
    46                     CommandName="RebindGrid" Visible='true'><img class="middle" alt="" src="../Images/Telerik/Refresh.gif" /> Refresh</asp:LinkButton>&nbsp;&nbsp;  
    47                 <asp:HyperLink NavigateUrl="#" ID="GenerateNewPins" runat="server" Visible='<%# NewMillennium.Authorization.UserHasPermission(NewMillennium.FunctionalityName.CreateEditReps) %>' 
    48                     onclick="OpenRadWindowCreateNewPins();return false;"><img class="middle" alt="" src="../Images/Telerik/new.gif" /> 
    49                         Generate New PINs</asp:HyperLink>&nbsp;&nbsp;  
    50                 <asp:LinkButton ID="lnlExportToExcel" runat="server" OnClick="ExportToExcelClick" 
    51                     Visible='true'><img class="middle" alt="" src="../Images/Telerik/excel.gif" /> Export</asp:LinkButton>&nbsp;&nbsp;  
    52                 &nbsp;  
    53             </CommandItemTemplate> 
    54             <Columns> 
    55                 <telerik:GridBoundColumn HeaderText="PinID" DataField="PINID" UniqueName="PINID" 
    56                     SortExpression="PINID" ReadOnly="true" Visible="false">  
    57                 </telerik:GridBoundColumn> 
    58                 <telerik:GridBoundColumn DataField="DateCreated" HeaderText="Date Generated" SortExpression="DateCreated" 
    59                     CurrentFilterFunction="Between" AutoPostBackOnFilter="true" UniqueName="DateCreated" 
    60                     DataFormatString="{0:M/d/yyyy}" AllowFiltering="false">  
    61                 </telerik:GridBoundColumn> 
    62                 <telerik:GridBoundColumn HeaderText="PIN" CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" 
    63                     DataField="PIN" UniqueName="PIN" SortExpression="PIN" ReadOnly="true" Visible="true">  
    64                 </telerik:GridBoundColumn> 
    65                 <telerik:GridBoundColumn HeaderText="Program" CurrentFilterFunction="StartsWith" 
    66                     AutoPostBackOnFilter="true" DataField="ProjectName" UniqueName="ProjectName" 
    67                     SortExpression="ProjectName" DataType="System.String" ReadOnly="true" Visible="true">  
    68                 </telerik:GridBoundColumn> 
    69                 <telerik:GridBoundColumn HeaderText="Rep First Name" CurrentFilterFunction="StartsWith" 
    70                     AutoPostBackOnFilter="true" DataField="RepFirstName" UniqueName="RepFirstName" 
    71                     SortExpression="RepFirstName" DataType="System.String" ReadOnly="true" Visible="true">  
    72                 </telerik:GridBoundColumn> 
    73                 <telerik:GridBoundColumn HeaderText="Rep Last Name" CurrentFilterFunction="StartsWith" 
    74                     AutoPostBackOnFilter="true" DataField="RepLastName" UniqueName="RepLastName" 
    75                     SortExpression="RepLastName" DataType="System.String" ReadOnly="true" Visible="true">  
    76                 </telerik:GridBoundColumn> 
    77                 <telerik:GridBoundColumn HeaderText="Territory Name" CurrentFilterFunction="StartsWith" 
    78                     AutoPostBackOnFilter="true" DataField="TerritoryName" UniqueName="TerritoryName" 
    79                     SortExpression="TerritoryName" ReadOnly="true" Visible="true">  
    80                 </telerik:GridBoundColumn> 
    81                 <telerik:GridBoundColumn HeaderText="Used" AutoPostBackOnFilter="true" DataField="UsedString" 
    82                     UniqueName="Used" SortExpression="UsedString" ReadOnly="true" Visible="true">  
    83                 </telerik:GridBoundColumn> 
    84                 <telerik:GridBoundColumn DataField="OrderDate" HeaderText="Date Used" SortExpression="OrderDate" 
    85                     CurrentFilterFunction="Between" AutoPostBackOnFilter="true" UniqueName="OrderDate" 
    86                     DataFormatString="{0:M/d/yyyy}" AllowFiltering="false">  
    87                 </telerik:GridBoundColumn> 
    88             </Columns> 
    89         </MasterTableView> 
    90     </telerik:RadGrid> 
    91 </asp:Content> 
    92  

    1 using System;  
    2 using System.Collections;  
    3 using System.Collections.Generic;  
    4 using System.Configuration;  
    5 using System.Data;  
    6 using System.Data.SqlClient;  
    7 using System.Web;  
    8 using System.Web.Security;  
    9 using System.Web.UI;  
    10 using System.Web.UI.HtmlControls;  
    11 using System.Web.UI.WebControls;  
    12 using NewMillennium;  
    13 using Telerik.Web.UI;  
    14  
    15 public partial class PinList : MillenniumPage  
    16 {  
    17     protected void Page_Load(object sender, EventArgs e)  
    18     {  
    19         if (!Authorization.UserHasPermission(FunctionalityName.ViewRepList)) FormsAuthentication.RedirectToLoginPage();  
    20         Common.SetGridSkin(PinGrid);  
    21     }  
    22     protected void PinGrid_PreRender(object sender, EventArgs e)  
    23     {  
    24  
    25     }  
    26     /// <summary>  
    27     ///  
    28     /// </summary>  
    29     protected void PinGrid_NeedDataSource(object source, GridNeedDataSourceEventArgs e)  
    30     {  
    31         PinGrid.DataSource = PinData.GetPinList();  
    32         Common.HideExtraFilterOptions(PinGrid);  
    33     }  
    34  
    35     protected void PinGrid_ItemCreated(object sender, GridItemEventArgs e)  
    36     {  
    37         Common.HideFilterButtonsForNewVersion(PinGrid, e.Item);  
    38     }  
    39  
    40     protected void ExportToExcelClick(object sender, EventArgs e)  
    41     {  
    42         string filename = "PinExport-" + DateTime.Now.ToLongDateString().Trim().Replace(" ""-").Replace(",""");  
    43  
    44         this.PinGrid.ExportSettings.FileName = filename;  
    45         this.PinGrid.ExportSettings.OpenInNewWindow = true;  
    46         this.PinGrid.ExportSettings.ExportOnlyData = true;  
    47         this.PinGrid.ExportSettings.IgnorePaging = true;  
    48  
    49         foreach (GridItem commandItem in this.PinGrid.MasterTableView.GetItems(GridItemType.CommandItem))  
    50         {  
    51             commandItem.Visible = false;  
    52         }  
    53  
    54         this.PinGrid.MasterTableView.ExportToExcel();  
    55     }  
    56     protected void PinGrid_ItemCommand(object sender, GridCommandEventArgs e)  
    57     {  
    58         if (e.CommandName == RadGrid.FilterCommandName && e.Item is GridFilteringItem)  
    59         {  
    60         }  
    61     }  
    62     protected void DisplayMessage(string message, string cssClass)  
    63     {  
    64         Message.Text = message;  
    65         Message.CssClass = cssClass;  
    66     }  
    67 }  
    68  
    69  


  2. Kelly
    Kelly avatar
    55 posts
    Member since:
    Nov 2007

    Posted 15 Apr 2009 Link to this post

    PS. The GetPinList() function in my code takes about 3 seconds to run - so it doesn't seem like the 20-minute performance issue would be related to that, unless something is going on behind the scenes that I don't know about (it's not loading the entire dataset for each row in the grid, correct?)
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Kelly
    Kelly avatar
    55 posts
    Member since:
    Nov 2007

    Posted 16 Apr 2009 Link to this post

    FYI, I was able to fix this with 2 setting changes:

    1) Switched to Html format instead of ExcelML for the excel file format. Not sure why, but one is apparently a lot faster than the other.

    2) Switched to client-side exporting instead of server-side exporting. This doesn't affect the performance for an export that finishes normally, but it does affect the web server CPU usage if the user closes their web browser or goes to a different page while waiting for the export to finish. With server-side exporting, web server CPU usage remains at 100% pretty much permanently after the request has been cancelled.  With client-side exporting, web server CPU usage goes back to normal if the request is cancelled.

    Public service announcement - when exporting the RadGrid to Excel, avoid exporting with ExcelML format, and avoid server-side exporting.  This issue completely froze my production web server yesterday and caused timeouts for every request (not just the PIN export).
  5. Peter
    Peter avatar
    60 posts
    Member since:
    Apr 2009

    Posted 21 Apr 2009 Link to this post

    Hi Kelly,

    I am a software developer. Currently, I am evaluating the Telerik's RadControls and everything is looking fine till now. I tried to use your scenario, but I couldn't find how to export the data on client-side. Actually I couldn't find any documentation how to export on client-side. Could you share your know-how about this?
    Did you perform any comparison between the ExcelML and the HTML export modes? Could you provide any statistics which show which mode give better performance?


    Regards,
    Peter
  6. Kelly
    Kelly avatar
    55 posts
    Member since:
    Nov 2007

    Posted 21 Apr 2009 Link to this post

    I had to dig to find the client-side documentation too, here's my page using the client-side export.

    With Html export my page with 67,000 records took 15 seconds to show the save/open dialog.  With ExcelML format the exact same export took 2 minutes to show the save/open dialog under good circumstances.  (With either method, the save/open dialog didn't show up at all after 20 minutes if the web server was at 100% CPU usage from a previous server-side export not finishing, so I think switching to client-side exporting is the most important.)

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PinList.aspx.cs" Inherits="PinList" 
        MasterPageFile="~/Admin/Masterpages/AdminPageWithMenu.master" Theme="MillenniumAdmin" 
        Title="PIN List" %> 
     
    <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %> 
    <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"
     
        <script type="text/javascript"
            function OpenRadWindowCreateNewPins() { 
                var oWindow = radopen("Popups/NewPIN.aspx", null); 
                oWindow.op 
                oWindow.SetSize(600, 520); 
            } 
     
            //Reloads PIN Grid  
            function OnClientClose(radWindow) { 
                location.reload(); 
            } 
            function ExportGrid() { 
                var masterTable = $find("<%=PinGrid.ClientID %>").get_masterTableView(); 
                masterTable.exportToExcel('PIN_list.xls'); 
                return false; 
            } 
        </script> 
     
    </asp:Content> 
    <asp:Content ID="Content2" ContentPlaceHolderID="PageTitle" runat="Server"
        PIN List 
    </asp:Content> 
    <asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"
        <telerik:RadWindowManager ID="winMgr" Skin="Outlook" Behaviors="Close, Move, Resize" 
            Modal="true" VisibleStatusbar="false" runat="server" Width="520px" Height="450px" 
            OnClientClose="OnClientClose"
        </telerik:RadWindowManager> 
        <asp:Label ID="Message" runat="server" EnableViewState="false"></asp:Label> 
        <telerik:RadGrid ID="PinGrid" runat="server" AutoGenerateColumns="false" AllowAutomaticDeletes="false" 
            AllowAutomaticInserts="false" AllowAutomaticUpdates="false" ShowStatusBar="true" 
            AllowMultiRowSelection="false" AllowPaging="true" PageSize="30" OnNeedDataSource="PinGrid_NeedDataSource" 
            OnItemCreated="PinGrid_ItemCreated" AllowFilteringByColumn="true" OnPreRender="PinGrid_PreRender" 
            OnItemCommand="PinGrid_ItemCommand" Width="90%" EnableAjaxSkinRendering="true"
            <ExportSettings ExportOnlyData="true" FileName="PINList" IgnorePaging="true" OpenInNewWindow="true"
                <Excel Format="Html" FileExtension="xls" /> 
            </ExportSettings> 
            <MasterTableView AllowNaturalSort="false" CommandItemDisplay="Top" DataKeyNames="PINID" 
                AutoGenerateColumns="false" AllowSorting="true"
                <PagerStyle Mode="NextPrevAndNumeric"></PagerStyle> 
                <CommandItemTemplate> 
                    <asp:LinkButton ID="lnlRebind" runat="server" OnClientClick="javascript:location.reload()" 
                        CommandName="RebindGrid" Visible='true'><img class="middle" alt="" src="../Images/Telerik/Refresh.gif" /> Refresh</asp:LinkButton>&nbsp;&nbsp; 
                    <asp:HyperLink NavigateUrl="#" ID="GenerateNewPins" runat="server" Visible='<%# NewMillennium.Authorization.UserHasPermission(NewMillennium.FunctionalityName.CreateEditReps) %>' 
                        onclick="OpenRadWindowCreateNewPins();return false;"><img class="middle" alt="" src="../Images/Telerik/new.gif" /> 
                            Generate New PINs</asp:HyperLink>&nbsp;&nbsp; 
                    <asp:LinkButton ID="lnlExportToExcel" runat="server" OnClientClick="return ExportGrid()" 
                        Visible='true'><img class="middle" alt="" src="../Images/Telerik/excel.gif" /> Export</asp:LinkButton>&nbsp;&nbsp; 
                    &nbsp; 
                </CommandItemTemplate> 
                <Columns> 
                    <telerik:GridBoundColumn HeaderText="PinID" DataField="PINID" UniqueName="PINID" 
                        SortExpression="PINID" ReadOnly="true" Visible="false"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn DataField="DateCreated" HeaderText="Date Generated" SortExpression="DateCreated" 
                        CurrentFilterFunction="Between" AutoPostBackOnFilter="true" UniqueName="DateCreated" 
                        DataFormatString="{0:M/d/yyyy}" AllowFiltering="false"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="PIN" CurrentFilterFunction="Contains" AutoPostBackOnFilter="true" 
                        DataField="PIN" DataFormatString="{0}&nbsp;" UniqueName="PIN" SortExpression="PIN" 
                        ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="Program" CurrentFilterFunction="StartsWith" 
                        AutoPostBackOnFilter="true" DataField="ProjectName" UniqueName="ProjectName" 
                        SortExpression="ProjectName" DataType="System.String" ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="Rep First Name" CurrentFilterFunction="StartsWith" 
                        AutoPostBackOnFilter="true" DataField="RepFirstName" UniqueName="RepFirstName" 
                        SortExpression="RepFirstName" DataType="System.String" ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="Rep Last Name" CurrentFilterFunction="StartsWith" 
                        AutoPostBackOnFilter="true" DataField="RepLastName" UniqueName="RepLastName" 
                        SortExpression="RepLastName" DataType="System.String" ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="Territory Name" CurrentFilterFunction="StartsWith" 
                        AutoPostBackOnFilter="true" DataField="TerritoryName" UniqueName="TerritoryName" 
                        SortExpression="TerritoryName" ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn HeaderText="Used" AutoPostBackOnFilter="true" DataField="UsedString" 
                        UniqueName="Used" SortExpression="UsedString" ReadOnly="true" Visible="true"
                    </telerik:GridBoundColumn> 
                    <telerik:GridBoundColumn DataField="OrderDate" HeaderText="Date Used" SortExpression="OrderDate" 
                        CurrentFilterFunction="Between" AutoPostBackOnFilter="true" UniqueName="OrderDate" 
                        DataFormatString="{0:M/d/yyyy}" AllowFiltering="false"
                    </telerik:GridBoundColumn> 
                </Columns> 
            </MasterTableView> 
        </telerik:RadGrid> 
        <div id="div_processing"
            <h3> 
                Exporting PINs</h3> 
            <p> 
                Exporting PIN list ... please wait.</p> 
            <p> 
                <center> 
                    <img src="../images/Telerik/progress.gif" /></center
            </p> 
        </div> 
        <div id="overlay"
        </div> 
    </asp:Content> 
     

  7. Peter
    Peter avatar
    60 posts
    Member since:
    Apr 2009

    Posted 21 Apr 2009 Link to this post

    Hi Kelly,

    Thank you for the statistics. I suppose the HTML mode could be faster, because the ExcelML conversion in general should be created after the grid creation. Anyway, I am just sharing my thoughts.

    I tried your scenario, but I am pretty confident that the export is still performed on server-side. I think the suggested method is a client method which calls a server Export method to perform the exporting of the RadGrid's data. In other words the exporting is still depending on the server, and does not export the data depending on the rendered HTML mark-up code. That's why I believe that there should be no difference between client "exportToExcel()" method and the server one. As I mentioned I couldn't notice the described difference.

    Regards,
    Peter
  8. Kelly
    Kelly avatar
    55 posts
    Member since:
    Nov 2007

    Posted 21 Apr 2009 Link to this post

    I agree the client-side and server-side export both depend on the server - I think they called it "client-side" because it's initiated on the client.

    The behavior I was seeing with the server-side export is this:
    1. Start a server-side export while monitoring CPU usage on the web server - web server CPU usage goes to 100%
    2. While it is exporting a large number of records, in the web browser, click on a link to a different page and/or close the web browser - web server CPU usage remains at 100% even though the export request has been cancelled.  At this point my users were re-trying the export and that would make it even worse - it basically crashed my web server and caused timeouts on every page in my website.

    The behavior I saw with the client-side export is:
    1. Start a client-side export while monitoring CPU usage on the web server - web server CPU usage goes to 100%
    2. While it is exporting a large number of records, in the web browser, click on a link to a different page and/or close the web browser - web server CPU usage goes back to normal.
  9. Peter
    Peter avatar
    60 posts
    Member since:
    Apr 2009

    Posted 21 Apr 2009 Link to this post

    Hi Kelly,

    Thank you for confirming my thoughts. I used the depicted scenario to create a test project which uses the both approaches. I bound the grid with 10000 rows. When I perform the export with the ExportToExcel (server-side) method and close the web browser, CPU usage stays 100% just for a few seconds more. After that it goes to a normal usage. If I export with the exportToExcel (client-side) method I noticed that there is a just a second difference in favor to the client-side method for exporting. So I still cannot replicate the described scenario. Maybe I am not doing something correctly in order to replicate this scenario. Could you provide a live link, which depicts this scenario?


    Regards,
    Peter
  10. Pradeep Deshpande
    Pradeep Deshpande avatar
    8 posts
    Member since:
    Sep 2009

    Posted 21 May 2015 Link to this post

    I am trying to export the 250000 records from telerik grid using "XLSX" format its taking 7 minutes to show the save link.

    Can we improve the performance of export to excel.

  11. Kostadin
    Admin
    Kostadin avatar
    1711 posts

    Posted 26 May 2015 Link to this post

    Hello Pradeep,

    The best approach is to create the Excel document manually by using the ExportInfrastructure. Please check out the following code library which demonstrates how to manually fetch the data from your datasource and create an Excel structure. Also I would suggest you to check out the following help article for additional information about ExportInfrastructure.

    Regards,
    Kostadin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017