Sql server Azure SQL数据库-索引10+;百万行
我的数据库托管在Azure SQL数据库上,下面是单个表的架构: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,
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
语句的性能。你必须衡量实际影响——这可能是可以接受的。这是你能做的最基本的索引。你需要一个指导。如果你不了解索引的第一件事,你会一次又一次地遇到这个问题。