Мой менеджер назначил мне проект, в соответствии с которым я использовал плагин jQuery Calendar для отображения календарных данных, хранящихся в различных таблицах в нашей базе данных SQL.
Это просто плагин jQuery, который принимает статические данные json и отображает их в календаре. Мне пришлось интегрировать его с .net и нашей базой данных SQL таким образом, чтобы календарь мог отображать данные из базы данных SQL (Microsoft SQL.)
Изначально мы собрали все вместе таким образом, чтобы мы извлекли все данные с сервера SQL, а затем использовали .Net для создания json, а затем передали его в плагин календаря jQuery.
Хотя в принципе это работало хорошо, оно было очень медленным, и IIS часто зависал. Не говоря уже о том, что каждый раз, когда кто-то из нас хотел просмотреть календарь, нам приходилось ждать около 3 минут, поскольку число записей приближается к 3000.
Запросы были довольно сложными, они на лету используют функции Dateadd и DateDiff и различные способы действий. Время выполнения только на сервере SQL составляло около 90 секунд для запроса. Общий размер запроса составил около 160 КБ.
Затем мы разбиваем запрос на 3 части (для разных отделов), но количество времени, которое мы должны ждать для составления календаря, все еще больше минуты.
Вот пример только одного из запросов, но их более 100 на отдел
CREATE TABLE #AnnualLastMonImportantCustomDate(
Title varchar(550) COLLATE Latin1_General_CI_AS NULL,
AllocatedDate varchar(550) COLLATE Latin1_General_CI_AS NULL,
EndDateTime varchar(550) COLLATE Latin1_General_CI_AS NULL,
url varchar(550) COLLATE Latin1_General_CI_AS NULL,
width varchar(10) COLLATE Latin1_General_CI_AS NULL,
height varchar(550) COLLATE Latin1_General_CI_AS NULL,
AllDay varchar(550) COLLATE Latin1_General_CI_AS NULL,
description varchar(550) COLLATE Latin1_General_CI_AS NULL,
color varchar(550) COLLATE Latin1_General_CI_AS NULL,
textColor varchar(550) COLLATE Latin1_General_CI_AS NULL
)
DECLARE db_cursor CURSOR FOR SELECT AlertDate FROM xsCRMAlerts
WHERE AlertType='InternalImportantDate'
-- cursor is the results row when table goes through fetch process
SET @MyTableName='xsCRMAlerts'
OPEN db_cursor -- opens the table and stores id, which is the primary key in the table
FETCH NEXT FROM db_cursor INTO @MyTableName -- @MyTableName in this case is the result row.
WHILE @@FETCH_STATUS = 0 -- 0 is for success -1 is for too many results -2 is for the row fetched is missing
BEGIN
-- Below between begin and end the statement is linked to a function, which gives the dates tabled based on a start date. This table is then cross joined to produce desired result.
SET @startDate = @MyTableName -- we can set the start date to all the data we recieved because we have only asked for one field in our @MyTableName query when db_cursor was being drawn
INSERT INTO #AnnualLastMonImportantCustomDate
SELECT
'Important Date : ' + [Title] as 'Title',
dr.date as 'AllocatedDate',
dr.date as 'EndDateTime' ,
'xsCRM_Dates_Edit.aspx?id=' + cast(id as varchar) as 'url' ,
'515px' as 'width',
'410px' as 'height',
'true' as 'allDay',
'Important date' as 'description', /* This is a static entry and will not show on the calendar. Used when redering object*/
'yellow' as 'color',
'black' as 'textColor'
FROM [DelphiDude].[dbo].[xsCRMAlerts]
cross JOIN
dateTable(
DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0)
,
DateAdd(yy,1,DATEADD(ms,-3,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,GETDATE())+1,0))))
) dr -- You can specify intervals by calling DateTable_Month, DateTable_Quarter, DateTable_BiAnnual and DateTable_Annual
WHERE
(AlertType='InternalImportantDate') and
(occurring='765') and
(Datepart(m,date) = 12) and
(Datepart(day,date) > 24) and
(Datepart(dw,date) = 2) and
(Datepart(year,date) = (Datepart(year,getDate()) + 1))
FETCH NEXT FROM db_cursor INTO @MyTableName -- gets the next record from the table
END
CLOSE db_cursor
DEALLOCATE db_cursor
Нам действительно нужны эти запросы.
Теперь мы думаем об ограничении набора результатов только предыдущими и последующими 30 днями.
Но каждый раз, когда мы оптимизируем запрос, я затем (даже если он использует только поиск и замену) должен реплицировать это изменение на 100 запросов на модуль.
Есть ли способ, которым мы можем оптимизировать эти запросы и ускорить выполнение и время рендеринга календаря, которое является окончательным и улучшает его в долгосрочной перспективе? И есть ли способ, которым я могу применить изменения таким образом, чтобы они реплицировались по каждому из запросов?
Я предложил своему боссу использовать кэширование, DB-кэширование и объектное кэширование, но он сказал, что данные будут часто меняться, и данные отсюда нужно передавать в другие модули, и поэтому, если они кэшируются, это может быть неточно. У меня недостаточно опыта, чтобы оспорить то, что он говорил.
Любой совет кто-нибудь?