Использование .NET для создания JSON? - PullRequest
0 голосов
/ 11 октября 2011

Мой менеджер назначил мне проект, в соответствии с которым я использовал плагин 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-кэширование и объектное кэширование, но он сказал, что данные будут часто меняться, и данные отсюда нужно передавать в другие модули, и поэтому, если они кэшируются, это может быть неточно. У меня недостаточно опыта, чтобы оспорить то, что он говорил.

Любой совет кто-нибудь?

1 Ответ

1 голос
/ 16 октября 2011

в запросе, который вы публикуете, курсор бесполезен, потому что вы никогда не используете переменную @startDate или @MyTableName в запросе вставки.

Таким образом, в вашу временную таблицу потенциально может быть вставлено много повторяющихся строк.

Кроме того, попробуйте использовать CTE или табличную переменную вместо "#Teorary table", потому что данные "#Teorary tables" физически хранятся в файловой системе и стоит много ввода-вывода, увеличивая время выполнения.

Последний совет: не забывайте создавать кластеризованные / некластеризованные индексы в вашей таблице xsCRMAlerts. Если вы используете SQL Server Management Studio, план выполнение или помощник по настройке ядра СУБД помогут вам найти недостающие индексы.

Надеюсь, это поможет:)

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