2015-01-11 2 views
1

У меня есть следующий код:Linq для лиц, операции таймаута при попытке использовать группу .. по

 var statList = (from i in _dbContext.Screenshots 
         where EntityFunctions.TruncateTime(i.dateTimeServer.Value) >= startDate && EntityFunctions.TruncateTime(i.dateTimeServer.Value) <= endDate 
         group i by EntityFunctions.TruncateTime(i.dateTimeServer.Value) 
          into g 
          select new ScreenshotStatistic() 
          { 
           Date = g.Key.Value, 
           AllScreenshots = g.Count(), 
           ScreenshotsNoSilent = g.Where(p => p.version.IndexOf("silent") == 0).Count(), 
           ScreenshotsNoSilentWithViews = g.Where(p => p.version.IndexOf("silent") == 0 && p.viewsPage + p.viewsOriginal > 0).Count(), 
           ScreenshotsOnlySilent = g.Where(p => p.version.IndexOf("silent") >= 0).Count(), 
           ScreenshotsOnlySilentWithViews = g.Where(p => p.version.IndexOf("silent") >= 0 && p.viewsPage + p.viewsOriginal > 0).Count(), 
           ScreenshotsOnlyUploadViaSite = g.Where(p => p.version.IndexOf("UPLOAD_VIA_SITE") >= 0).Count(), 
           ScreenshotsOnlyUploadViaSiteWithViews = g.Where(p => p.version.IndexOf("UPLOAD_VIA_SITE") >= 0 && p.viewsPage + p.viewsOriginal > 0).Count() 
          }).ToList(); 

Он работает тщательно для моей локальной базы данных, но я получаю сообщение «Операция тайм-аут», когда я пытаюсь подключитесь к SQL Azure. Насколько я понимаю, мой запрос не оптимизирован. Как я могу сделать запрос лучше?

таблица имеет следующую структуру:

CREATE TABLE [dbo].[Screenshots](
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [dateTimeClient] [datetime] NOT NULL, 
    [name] [nvarchar](500) NOT NULL, 
    [username] [varchar](50) NULL, 
    [filename] [nvarchar](50) NULL, 
    [description] [nvarchar](500) NULL, 
    [version] [varchar](50) NULL, 
    [lang] [varchar](50) NULL, 
    [dateTimeServer] [datetime] NULL CONSTRAINT [DF_Screenshots_dateTimeServer] DEFAULT (getdate()), 
    [isPublic] [bit] NOT NULL CONSTRAINT [DF_Screenshots_isPublic] DEFAULT ((0)), 
    [viewsPage] [int] NOT NULL CONSTRAINT [DF_Screenshots_viewsPage_1] DEFAULT ((0)), 
    [viewsThumb] [int] NOT NULL CONSTRAINT [DF_Screenshots_viewsThumb_1] DEFAULT ((0)), 
    [viewsOriginal] [int] NOT NULL CONSTRAINT [DF_Screenshots_viewsOriginal_1] DEFAULT ((0)), 
    [statusID] [int] NOT NULL, 
CONSTRAINT [PK_Screenshots] PRIMARY KEY CLUSTERED 
(
    [id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

SET ANSI_PADDING OFF 
GO 

ALTER TABLE [dbo].[Screenshots] WITH CHECK ADD CONSTRAINT [FK_Screenshots_ScreenshotStatuses] FOREIGN KEY([statusID]) 
REFERENCES [dbo].[ScreenshotStatuses] ([ID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[Screenshots] CHECK CONSTRAINT [FK_Screenshots_ScreenshotStatuses] 
GO 
+0

Что вы пытаетесь достичь? и какое хранилище вы используете на Azure? например SQL, Table, Blob? – Dennis

+0

Я могу помочь вам улучшить ваш запрос, однако я думаю, что мы сможем получить лучший результат с дополнительной информацией. – Dennis

+0

Не могли бы вы перестроить ввод этой информации, чтобы при сохранении вы разрывали компоненты даты и времени и записывали их для разделения свойств в базе данных? Кроме того, обеспечили ли вы наличие индексов в столбце в Azure? Вам также может потребоваться изменить уровень вашей базы данных Azure SQL, чтобы повысить производительность. –

ответ

1

EntityFunctions.TruncateTime переводится на:

convert (datetime2, convert(varchar(255), [dateTimeServer], 102) , 102) 

Это вызывает ваш запрос будет non-sargable, что приводит к снижению производительности и тайм-аут. Я рекомендую сделать следующие изменения


Во-первых, я не понимаю, почему вам нужно усечь время в вашей статье where. Я предлагаю вам внести это изменение:

where i.dateTimeServer.Value >= startDate && i.dateTimeServer.Value <= endDate 

Это предотвратит запуск базы данных для каждой функции.


Если запрос еще раз, я бы изменить group by к:

group i by new { 
    i.dateTimeServer.Value.Year, 
    i.dateTimeServer.Value.Month, 
    i.dateTimeServer.Value.Day 
} 

Функционально это то же самое, но я считаю, что это производит более дружественный перевод:

DATEPART (year, dateTimeServer), DATEPART (month, dateTimeServer) etc.. 

Добавить индекс в dateTimeServer


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

+0

Как создать этот индекс? Насколько я понимаю, я должен создать индекс без времени? Я пытаюсь создать, но не могу урезать время http://www.magicscreenshot.com/jpg/6u64wnWw3kQ.html –

+1

@OlegSh - Вы не можете создать индекс без времени. Является ли запрос еще тайм-аутом при создании индекса 'dateTimeServer'? – Aducci

+0

вы пишете мне «Добавить индекс на DateTimeServer». Какой смысл в индексе со временем? –

Смежные вопросы