как кешировать мультиплатформенные наборы?или заставьте медленную страницу asp.net работать быстрее - PullRequest
0 голосов
/ 17 декабря 2010

Моя страница загружается медленно, я загружаю информацию из 2 гигантских просмотров данных, чтобы получить информацию об истории продаж, в таблицу. Я загружаю информацию, основанную на вчерашних продажах / числах. Я хочу кешировать данные, но как я могу это сделать, если мой запрос зависит от выбранного года и информации, которую хочет пользователь. Я думал, что будет лучше кэшировать страницы.

Если у вас есть какие-либо другие рекомендации, чтобы загрузить или сделать это более эффективным способом, пожалуйста, помогите.

Помогите ли я добавить параметр вместо моего dropdownlist.value в моем запросе?

 saocmd.Connection = conn
            conn.Open()

            If RadioButtonList1.SelectedValue = "Sales" Then
                saocmd.CommandText = "SELECT B603SalesAsOFMASTER.SDESCR, B603SalesAsOFMASTER.DYYYY, B603SalesAsOFMASTER.AsOFSales, B603SalesAsOFMASTER.ASOFPAX, B603SalesAsOFMASTER.YESales, B603SalesAsOFMASTER.YEPAX, B603SalesAsOFMASTER.PCTofSales, B601SalesAsOF.Sales AS CurrentSales, B601SalesAsOF.PAX AS CurrentPAX FROM B603SalesAsOFMASTER INNER JOIN B601SalesAsOF ON B603SalesAsOFMASTER.SDESCR = B601SalesAsOF.SDESCR WHERE (B603SalesAsOFMASTER.DYYYY =" & DropDownList1.SelectedValue & ") AND (B601SalesAsOF.DYYYY = (year( getdate() ))) order by B603SalesAsOFMASTER.SDESCR"
                Label2.Text = "Sales"
            ElseIf RadioButtonList1.SelectedValue = "NetSales" Then
                saocmd.CommandText = "SELECT B603SalesAsOFMASTER.SDESCR, B603SalesAsOFMASTER.DYYYY, (ISNULL(B603SalesAsOFMASTER.AsOFNET,0)+ISNULL(B603SalesAsOFMASTER.AsOfOTHer,0)) as AsOfSales, B603SalesAsOFMASTER.ASOFPAX, (ISNULL(B603SalesAsOFMASTER.YENET,0)+ISNULL(B603SalesAsOFMASTER.YEOTHER,0)) as YESales, B603SalesAsOFMASTER.YEPAX, B603SalesAsOFMASTER.PCTofSales, (ISNULL(B601SalesAsOF.NETSales,0)+ ISNULL(B601SalesAsOF.OtherSales,0)) AS CurrentSales, B601SalesAsOF.PAX AS CurrentPAX FROM B603SalesAsOFMASTER INNER JOIN B601SalesAsOF ON B603SalesAsOFMASTER.SDESCR = B601SalesAsOF.SDESCR WHERE (B603SalesAsOFMASTER.DYYYY =" & DropDownList1.SelectedValue & ") AND (B601SalesAsOF.DYYYY = (year( getdate() ))) order by B603SalesAsOFMASTER.SDESCR"
                Label2.Text = "Net Sales"
            ElseIf RadioButtonList1.SelectedValue = "INSSales" Then
                saocmd.CommandText = "SELECT B603SalesAsOFMASTER.SDESCR, B603SalesAsOFMASTER.DYYYY, ISNULL(B603SalesAsOFMASTER.AsOFINS,0) as AsOFSales, B603SalesAsOFMASTER.ASOFPAX, ISNULL(B603SalesAsOFMASTER.YEINS,0) as YESales, B603SalesAsOFMASTER.YEPAX, B603SalesAsOFMASTER.PCTofSales,ISNULL(B601SalesAsOF.INSSales,0) AS CurrentSales, B601SalesAsOF.PAX AS CurrentPAX FROM B603SalesAsOFMASTER INNER JOIN B601SalesAsOF ON B603SalesAsOFMASTER.SDESCR = B601SalesAsOF.SDESCR WHERE (B603SalesAsOFMASTER.DYYYY =" & DropDownList1.SelectedValue & ") AND (B601SalesAsOF.DYYYY = (year( getdate() ))) order by B603SalesAsOFMASTER.SDESCR"
                Label2.Text = "Insurance Sales"
            ElseIf RadioButtonList1.SelectedValue = "CXSales" Then
                saocmd.CommandText = "SELECT B603SalesAsOFMASTER.SDESCR, B603SalesAsOFMASTER.DYYYY, ISNULL(B603SalesAsOFMASTER.AsOFCX,0)as AsOfSales, B603SalesAsOFMASTER.ASOFPAX, ISNULL(B603SalesAsOFMASTER.AsOFCX,0) as YESales, B603SalesAsOFMASTER.YEPAX, B603SalesAsOFMASTER.PCTofSales, ISNULL(B601SalesAsOF.CXSales,0) AS CurrentSales, B601SalesAsOF.PAX AS CurrentPAX FROM B603SalesAsOFMASTER INNER JOIN B601SalesAsOF ON B603SalesAsOFMASTER.SDESCR = B601SalesAsOF.SDESCR WHERE (B603SalesAsOFMASTER.DYYYY =" & DropDownList1.SelectedValue & ") AND (B601SalesAsOF.DYYYY = (year( getdate() ))) order by B603SalesAsOFMASTER.SDESCR"
                Label2.Text = "Canceled Sales"
            End If

            'selects sql query
            'saocmd.CommandText = "SELECT B603SalesAsOFMASTER.SDESCR, B603SalesAsOFMASTER.DYYYY, B603SalesAsOFMASTER.AsOFSales, B603SalesAsOFMASTER.ASOFPAX, B603SalesAsOFMASTER.YESales, B603SalesAsOFMASTER.YEPAX, B603SalesAsOFMASTER.PCTofSales, B601SalesAsOF.Sales AS CurrentSales, B601SalesAsOF.PAX AS CurrentPAX FROM B603SalesAsOFMASTER INNER JOIN B601SalesAsOF ON B603SalesAsOFMASTER.SDESCR = B601SalesAsOF.SDESCR WHERE (B603SalesAsOFMASTER.DYYYY =" & DropDownList1.SelectedValue & ") AND (B601SalesAsOF.DYYYY = (year( getdate() ))) order by B603SalesAsOFMASTER.SDESCR"
            saoda.Fill(saods, "salesasoftable")

            'does the math for the Percent of PAX
            Dim pctofpax As New DataColumn
            pctofpax = New DataColumn("PCTPAX1", GetType(Decimal))
            pctofpax.Expression = "[ASOFPAX] / [YEPAX]"
            saods.Tables("salesasoftable").Columns.Add(pctofpax)

            'does the math for the average per passanger
            Dim avgppax As New DataColumn
            avgppax = New DataColumn("AVGPAX", GetType(Double))
            avgppax.Expression = "CurrentSales / CurrentPAX"
            saods.Tables("salesasoftable").Columns.Add(avgppax)

            'gets the projected sales by dividing the currentsales by the percent of sales
            Dim projectedye As New DataColumn
            projectedye = New DataColumn("ProjSales", GetType(Double))
            projectedye.Expression = "IIF([PCTofSales] = 0, [CurrentSales], [CurrentSales] / [PCTofSales])"
            saods.Tables("salesasoftable").Columns.Add(projectedye)



            'gets the projected amount of passangers by dividing the current amount of passengers by the percent of pax
            Dim projectedyep As New DataColumn
            projectedyep = New DataColumn("ProjPAX", GetType(Double))
            projectedyep.Expression = "CurrentPAX / PCTPAX1"
            saods.Tables("salesasoftable").Columns.Add(projectedyep)

            'gets the difference between projected sales and current sales
            Dim differencesales As New DataColumn
            differencesales = New DataColumn("remainingsales", GetType(Double))
            differencesales.Expression = "ProjSales - currentsales"
            saods.Tables("salesasoftable").Columns.Add(differencesales)

            'gets the difference in projected passengers and current passengers
            Dim differencepax As New DataColumn
            differencepax = New DataColumn("remainingpax", GetType(Double))
            differencepax.Expression = "Projpax - currentpax"
            saods.Tables("salesasoftable").Columns.Add(differencepax)

            GridView1.DataSource = saods

Ответы [ 6 ]

2 голосов
/ 17 декабря 2010

Ваш сайт уязвим для SQL-инъекций . Я хотел бы исправить это, прежде чем делать что-либо еще.

Что касается медлительности, я бы сосредоточился на том, насколько быстро выполняется ваш запрос. Можете ли вы предоставить нам план выполнения для особенно медленного запроса. С самого начала я бы сказал, избавиться от ORDER BY. Вы можете сделать это на стороне клиента ...

Убедитесь, что у вас есть правильные индексы на месте. В последнем случае вы можете посмотреть на год в качестве параметра (этот последний - всего лишь выстрел в темноте).

1 голос
/ 17 декабря 2010

Избавьтесь от конкатенации строк при создании оператора select. Это причиняет вам боль двумя способами:

  • Оставляет вас открытыми для SQL-инъекции
  • Заполняет сервер базы данных различными запросами, каждый раз вызывая жесткий анализ

Вместо этого используйте параметризованный запрос с заполнителями и установите значения параметров на основе ввода пользователя.

Вот краткое обсуждение:

http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html

1 голос
/ 17 декабря 2010

Два существенных факта, которые я вижу здесь: (1) узкое место считывается из вашей базы данных OLTP из-за сложного запроса (2) данные, которые вам нужны, несколько устарели (вчера) и не подлежат изменению в течение срока действиядень.

Я автоматически подумываю использовать datamart или хранилище данных для такой ситуации.Ночью вы запускаете задания служб SSIS для обновления данных datamart, а затем они становятся доступными для запроса, когда руководители прибудут утром.Datamart может быть денормализован для повышения производительности запросов - фактически, это обычно поощряется.Я был бы удивлен, если бы производительность вашего запроса не улучшилась хотя бы на порядок.Дополнительным преимуществом этого подхода является то, что у вас под рукой будут все возможности SSAS по составлению отчетов и анализу.Есть руководители, которым нравится иметь возможность разрезать и нарезать кубики данных в аналитическом кубе, поэтому они могут считать вас ИТ-рок-звездой, если вы предоставите им эту возможность.Еще одно преимущество заключается в том, что витрина данных может предоставляться и управляться отдельно от вашей базы данных OLTP, а это означает, что другие пользователи вашего веб-приложения не будут замечать медленной производительности во время выполнения этих запросов.И последнее преимущество заключается в том, что SSAS действительно хорошо разбивает ваши данные по известным измерениям (например, по годам).

Если у вас недостаточно пропускной способности для настройки отдельного хранилища данных / хранилища данных, вы, безусловно, могли бысделайте нечто подобное в пределах вашей базы данных OLTP.Вы бы упустили возможности SSAS и сегрегацию сложных запросов, но вы могли бы попытаться развернуть витрину данных в будущем выпуске.Один из подходов в вашей существующей БД может заключаться в настройке индексированных представлений, но это может привести к серьезным затратам времени выполнения из-за необходимости обновления представления при каждом обновлении связанных данных.Возможно, лучшим подходом было бы просто создать денормализованные таблицы в вашей базе данных OLTP с конкретной миссией обслуживания этих специализированных запросов.Просто запланируйте работу на вечер, чтобы обновить столы.Вы могли бы даже использовать SSIS для этого, хотя это может быть излишним, если все происходит в пределах одной БД.Возможно, будет достаточно оператора SQL или операторов.

При любом подходе я бы предложил выполнить вычисления на уровне базы данных.Я не вижу никакого преимущества в расчете их на лету, так как они не будут меняться в течение дня.Заполнение вычисляемых столбцов должно быть выполнено как часть ночной обработки.

1 голос
/ 17 декабря 2010

Возможно, ваша проблема вообще не связана с базой данных.Если вы привязываете миллион результатов к DataGrid и не используете подкачку страниц, то это всего лишь много HTML, чтобы продвинуться вниз.Если вы создаете страничные результаты так, что вы только «отображаете» десять из миллиона записей, возвращенных из базы данных, но у вас включен ViewState в DataGrid, тогда все эти записи сериализуются и все равно отправляются в браузер.Лучше всего реализовать пользовательский пейджинг, вернув из базы данных только десять (или 20, или 50) записей, которые вы хотите отобразить.

Ознакомьтесь с этой статьей на 4Guys о том, как реализовать пользовательский пейджинг.

0 голосов
/ 17 декабря 2010

Почему бы не составить таблицу с результатами за каждый год раз и навсегда? Похоже, его исторические данные не должны меняться.

Migth не решает проблемы с производительностью, но все же выгружает некоторую нагрузку.

Ура, Stefan

0 голосов
/ 17 декабря 2010

Кстати, я не думаю, что у вас есть уязвимость SQL-инъекций, поскольку единственный пользовательский ввод, включенный в запрос, происходит из выпадающего списка.Пока единственные значения, доступные в раскрывающемся списке, устанавливаются приложением, не должно быть опасности злонамеренного ввода пользовательских данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...