2016-03-24 4 views
0

У меня очень простой один запрос таблицы, который занимает много секунд. Я озадачен. Когда я перехожу от select top до 50 вместо 200, он идет намного быстрее. Стол имеет около миллиона строк.Производительность сервера Sql Не то, что я ожидал

У меня есть индексы на всех упомянутых столбцах.

SELECT TOP 50 dbo.EmailDetails.Id, 
FROM dbo.EmailDetails WITH (NOLOCK) 
WHERE (dbo.EmailDetails.EmailSendStatus = 'NEEDTOSEND' OR 
    dbo.EmailDetails.EmailSendStatus = 'NEEDTOTEXT') AND 
    dbo.EmailDetails.EmailDetailsTopicId IS NOT NULL 
ORDER BY dbo.EmailDetails.EmailSendPriority, 
    dbo.EmailDetails.Id DESC 

План Сформировать является:

enter image description here

и Full DDL является:

CREATE TABLE dbo.EmailDetails (
     Id int IDENTITY(1, 1) NOT NULL, 
     AttendeesId int NOT NULL, 
     SponsorListContactId int NULL, 
     MessageUniqueId nvarchar(512) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailSendStatus nvarchar(16) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailSendStartTime datetime NULL, 
     EmailSendFinishTime datetime NULL, 
     EmailSendLogMessage nvarchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     Subject nvarchar(2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     BodyText nvarchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     SentDateTime datetime NULL, 
     EmailFrom nvarchar(128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailTo nvarchar(128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     EmailDetailsTopicId int NULL, 
     EmailDetailsGuid uniqueidentifier NULL, 
     EmailReadCount int NULL, 
     EmailReadDate datetime NULL, 
     EmailSendStatusChange datetime NULL, 
     EmailSendPriority int NULL, 
     TextTo varchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
     CONSTRAINT EmailDetails_pk PRIMARY KEY CLUSTERED (Id) 
     WITH (
      PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF, 
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
    ) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_AttendeesIds_idx ON dbo.EmailDetails 
     (AttendeesId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx ON dbo.EmailDetails 
     (EmailDetailsGuid) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx2 ON dbo.EmailDetails 
     (EmailDetailsTopicId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_idx3 ON dbo.EmailDetails 
     (SentDateTime) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_priority_status_idx4 ON dbo.EmailDetails 
     (EmailSendPriority, EmailSendStatus) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_SentStatus_idx ON dbo.EmailDetails 
     (EmailSendStatus) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_topicid_attendeeid ON dbo.EmailDetails 
     (EmailDetailsTopicId, AttendeesId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 

    CREATE NONCLUSTERED INDEX EmailDetails_topicid_sponsorcontactid_idx ON dbo.EmailDetails 
     (EmailDetailsTopicId, SponsorListContactId) 
    WITH (
     PAD_INDEX = OFF, 
     DROP_EXISTING = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     SORT_IN_TEMPDB = OFF, 
     ONLINE = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY] 
    GO 
+0

У вас есть конкретный вопрос? – B540Glenn

+0

Вы знаете, что такое план запроса? EXPORT IT (.sqlplan), а затем мы можем помочь. – TomTom

+0

Быстрее на 200 было просто, вероятно, строки/индексы в памяти. 50 против 200 он еще должен сортировать. – Paparazzi

ответ

3

При использовании SELECT TOP x вместе с ORDER BY рекомендуется в целом, чтобы обеспечить те же результаты каждый время, ORDER BY будет сортировать весь результирующий набор, и только тогда принимается TOP x f Ром это.

Интересно, что вы увидите, если вы делаете SELECT COUNT(*) вместо SELECT TOP x: возможно, довольно большое число?

И при использовании индексов гарантирует быструю сортировку, есть индекс no, который покрывает точный ORDER BY этого запроса. Кроме того, получение полей для предложений WHERE и SELECT требует ввода данных, которые, вероятно, распространяются по всему диску. Чтобы оптимизировать только этот запрос, вы можете добавить WHERE- и ORDER BY- и SELECT-поля к новому индексу (в этом порядке), конечно, без дубликатов. Это приведет к довольно большому индексу, который может замедлить вставки/обновления, но он также сделает SELECT очень быстрым, потому что тогда весь запрос может быть удовлетворен с использованием только индекса, не вдаваясь в данные.

+0

благодарит всех за ввод. Я отправлю план, когда вернусь к своему столу, и проведу счет (*). –

+0

Выполнение select count (*) очень быстрое (мгновенное), поэтому я предполагаю, что это не проблема индекса. Поскольку я уменьшаю количество столбцов, которые я извлекаю, он становится все быстрее и быстрее. Я полагаю, это означает, что мои данные должны быть разбросаны по диску? В любом случае, чтобы последние записи были близки друг к другу? Верхние записи всегда 10 или 20 тысяч, которые я только что вставил. –

+0

Значение count (\ *) дает указание количества работы, которое должен выполнить ORDER BY до того, как TOP x может быть взят, особенно если нет единого индекса, который покрывает поля ORDER BY. Скорость подсчета (\ *) сама по себе не так актуальна, и даже возможно, что ORDER BY пропущен, если запрошен счетчик (\ *) и никаких других полей. Что еще более важно - создать индекс более или менее, как я указал. –

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