Sql server Azure SQL数据库-索引10+;百万行

Sql server Azure SQL数据库-索引10+;百万行,sql-server,azure,indexing,azure-sql-database,Sql Server,Azure,Indexing,Azure Sql Database,我的数据库托管在Azure SQL数据库上,下面是单个表的架构: CREATE TABLE [dbo].[Article]( [ArticleHash] [bigint] NOT NULL, [FeedHash] [bigint] NOT NULL, [PublishedOn] [datetime] NOT NULL, [ExpiresOn] [datetime] NOT NULL, [DateCreated] [datetime] NOT NULL,

我的数据库托管在Azure SQL数据库上,下面是单个表的架构:

CREATE TABLE [dbo].[Article](
    [ArticleHash] [bigint] NOT NULL,
    [FeedHash] [bigint] NOT NULL,
    [PublishedOn] [datetime] NOT NULL,
    [ExpiresOn] [datetime] NOT NULL,
    [DateCreated] [datetime] NOT NULL,
    [Url] [nvarchar](max) NULL,
    [Title] [nvarchar](max) NULL,
    [Summary] [nvarchar](max) NULL
 CONSTRAINT [PK_dbo.Article] PRIMARY KEY CLUSTERED 
(
    [ArticleHash] ASC,
    [FeedHash] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
由于此表包含超过1000万条记录,我执行的一些查询速度非常慢:

SELECT * 
FROM (SELECT ROW_NUMBER() OVER (ORDER BY PublishedOn DESC) page_rn, *
      FROM Article
      WHERE (FeedHash = -8498408432858355421 AND ExpiresOn > '2016-01-18 14:18:04.970')
     ) paged 
WHERE page_rn>0 AND page_rn<=21 

索引此表以便查询在300毫秒以下执行的最佳方法是什么?在这么大的桌子上有可能吗?Azure SQL数据库版本是S3


此外,在此表上执行了许多删除/插入操作,因此任何索引都不应影响这些的性能…

第一次查询将受益于使用
偏移量
获取

SELECT * 
FROM Article
WHERE FeedHash = -8498408432858355421 AND ExpiresOn > '2016-01-18 14:18:04.970'
ORDER BY PublishedOn DESC
OFFSET 0 FETCH NEXT 20 ROWS ONLY
第二个查询可能会受益于将列表中的
替换为表的
内部联接

DECLARE @ArticleHashList AS TABLE (ArticleHashWanted bigint PRIMARY KEY);
INSERT INTO @ArticleHashList (ArticleHashWanted) VALUES
    (-1776401574438488264),
    (  996871668263687248),
    (-5186412434178204433),
    ( 6410875610077852481),
    (-5428137965544411137),
    (-5326808411357670185),
    ( 2738089298373692963),
    ( 9180394103094543689),
    ( 8120572317154347382),
    ( -369910952783360989),
    ( 1071631911959711259),
    ( 1187953785740614613),
    ( 6665010324256449533),
    ( 3720795027036815325),
    (-5458296665864077096),
    (-5832860214011872788),
    (-2941009192514997875),
    (  334202794706549486),
    (-5579819992060984166),
    ( -696086851747657853),
    (-7466754676679718482),
    (-1461835507954240474),
    ( 9021713212273098604),
    (-6337379666850984216),
    ( 5502287921912059432);

SELECT ArticleHash
FROM Article
INNER JOIN @ArticleHashList On ArticleHash = ArticleHashWanted
WHERE FeedHash = -8498408432858355421 AND ExpiresOn >= '2016-01-18 14:28:25.883';
在日期上创建索引应该会有很大帮助:

CREATE INDEX idx_Article_PublishedOn ON Article (PublishedOn);
CREATE INDEX idx_Article_ExpiresOn ON Article (ExpiresOn);

对于第一个查询,我建议使用此索引:

create index ix_Article_FeedHash_ExpiresOn_withInclude on Article(FeedHash,ExpiresOn) include ( DateCreated, PublishedOn, Url, Title, Summary)
第二个查询应该使用聚集索引查找,您必须查看实际执行计划。另外,我认为聚集索引很糟糕,因为值看起来并没有增长,但必须是随机的,而且可能索引非常零碎,您可以使用查询来检查它

select * from sys.dm_db_index_physical_stats(db_id(), object_id('Article'), null, null, 'DETAILED');
如果平均碎片百分比介于5和30之间,则可以通过

alter index [clustered index name] on Article reorganize;
alter index [clustered index name] on Article rebuild;
如果平均碎片百分比高于30,则可以通过

alter index [clustered index name] on Article reorganize;
alter index [clustered index name] on Article rebuild;

(如果重新组织后没有任何变化,那么您可以尝试重新构建)

您需要在ExpiresOn列上建立索引,publishOnI还会将
FeedHash
添加到与添加的
ExpiresOn
相同的索引中。此外,仔细检查执行计划会告诉您在何处执行表扫描以及扫描的值。因此,尝试用索引查找替换这些表扫描。要知道索引此表的最佳方法,必须了解此表中的数据分布。例如:10M行中有多少不同的
feedhash
,在典型的
ExpiresOn>过滤器之后,10M行中剩下多少行;
ArticleHash
列的选择性是什么。在任何情况下,任何额外的索引都肯定会影响
DELETE
INSERT
语句的性能。你必须衡量实际影响——这可能是可以接受的。这是你能做的最基本的索引。你需要一个指导。如果你不了解索引的第一件事,你会一次又一次地遇到这个问题。