Sql Server性能不是我所期待的

时间:2016-03-24 16:39:01

标签: sql-server

我有一个非常简单的一个表查询,需要很多秒才能完成。我感到很困惑。当我从select top更改为50而不是200时,它会更快。该表有大约一百万行。

我在所有提到的列上都有索引。

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

并且完整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

1 个答案:

答案 0 :(得分:2)

虽然建议将SELECT TOP xORDER BY一起使用以确保每次都能获得相同的结果,ORDER BY会对整个结果集进行排序,然后才会对TOP x进行排序从它。

我想知道如果你做SELECT COUNT(*)而不是SELECT TOP x,你会看到什么:可能是一个相当高的数字?

虽然使用索引可以保证快速排序,但 no 索引涵盖了此查询的确切ORDER BY。最重要的是,获取WHERE和SELECT子句的字段需要进入可能遍布整个磁盘的数据页。要优化此查询,您可以将WHERE-和ORDER BY-和SELECT-字段添加到新索引(按此顺序),当然不需要重复。它会产生一个相当大的索引,这可能会减慢插入/更新速度,但它也会使SELECT非常快,因为只需使用索引就可以满足整个查询,而无需进入数据页。