首先,我想提一下,我已经检查了所有其他问题,但没有一个与我的相似,所以我不认为这是重复的。
我有两个表格,“Article_tbl”到目前为止有超过300,000行,而“ArticleZone_tbl”的行数几乎相同。
“Article_tbl”包含Identity主键“ArticleID”。 “ArticleZone_tbl”包含由三列组成的主键,“ArticleID”,“ChannelID”,“ZoneID”;其中“ArticleID”是“Article_tbl”
中的外键在列上创建非聚集索引以按顺序排序。
SQL查询:
WITH OrderedOrders AS(
Select ROW_NUMBER() Over(Order by LastEditDate desc, ArticleOrder Asc, LastEditDateTime desc) as RowNum, dbo.Article_tbl.*, ArticleZone_tbl.ChannelID, ArticleZone_tbl.ZoneID, ArticleZone_tbl.ArticleOrder
From Article_tbl INNER JOIN ArticleZone_tbl
ON dbo.Article_tbl.ArticleID = dbo.ArticleZone_tbl.ArticleID
Where ChannelID=1 And ZoneID=0)
SELECT * FROM OrderedOrders Where RowNum Between 1 And 10
以上查询大约需要2秒钟才能完成,有没有办法优化此查询?
更多信息: 操作系统:Windows WebServer 2008R2 SQL Sever:2008R2 内存:32GB 硬盘:160GB SSD
提前致谢。
祝你好运, McHaimech
答案 0 :(得分:4)
您可以尝试在两个表格上创建Indexed View:
CREATE VIEW dbo.YourIndexedView
WITH SCHEMABINDING
AS
SELECT az.ArticleID,
az.ChannnelID,
az.ZoneID,
a.LastEditDate,
a.LastEditDateTime,
az.ArticleOrder
FROM dbo.Article_tbl a
INNER JOIN dbo.ArticleZone_tbl az
ON a.ArticleID = az.AtricleID;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_YourIndexView_ArticleID_ChannelID_ZoneID
ON dbo.YourIndexedView (ArticleID, ChannelID, ZoneID);
准备好聚集索引后,您可以创建一个非聚集索引来帮助进行排序:
CREATE NONCLUSTERED INDEX IX_YourIndexedView_LastEditDate_ArticleOrder_LastEditDateTime
ON dbo.YourIndexedView (LastEditDate DESC, ArticleOrder ASC, LastEditDateTime DESC);
然后,您可以在查询中引用它:
WITH OrderedOrders AS
( SELECT RowNum = ROW_NUMBER() OVER(ORDER BY LastEditDate DESC, ArticleOrder ASC, LastEditDateTime DESC),
ArticleID,
ChannelID,
ZoneID,
LastEditDateTime,
ArticleOrder
FROM dbo.YourIndexedView WITH (NOEXPAND)
WHERE ChannelID = 1
AND ZoneID = 0
)
SELECT *
FROM OrderedOrders
WHERE RowNum BETWEEN 1 AND 10;
N.B。我可能错过了您的文章表中的某些列,但我无法从问题
中推断出它们此外,如果您的查询始终具有相同的区域和频道,则可以过滤视图,然后您的聚集索引列将变为ArticleID
:
CREATE VIEW dbo.YourIndexedView
WITH SCHEMABINDING
AS
SELECT az.ArticleID,
az.ChannnelID,
az.ZoneID,
a.LastEditDate,
a.LastEditDateTime,
az.ArticleOrder
FROM Article_tbl a
INNER JOIN ArticleZone_tbl az
ON a.ArticleID = az.AtricleID
WHERE az.ChannelID = 1
AND Az.ZoneID = 1;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_YourIndexView_ArticleID
ON dbo.YourIndexedView (ArticleID);
这意味着您的索引会更小,使用起来更快。
答案 1 :(得分:1)
如你所说“相同查询”Over(按Article_tbl.ArticleID asc排序)“需要40ms”,毫无疑问你缺少一个索引。您应该研究查询计划(包括SSMS中的实际执行计划按钮) 所有字段覆盖您的OVER(ORDER BY ..)的一个索引可能会给您带来好的结果。 ArticleId在这里是有意义的,因为它是你的集群,尊重你的OVER子句的ASC / DESC命令。
尝试:
CREATE INDEX xxx on Article_tcl(LastEditDate desc, ArticleOrder asc, LastEditDateTime desc)
asc是您不需要指定的默认值,此处为了清晰起见
答案 2 :(得分:0)
我将查询分解为组件部分。具体来说,您不需要返回子查询中的所有列数据,这些数据确定行号和主键。此外,分解查询将使调试和优化变得更加容易。
CREATE TABLE #OrderedRows( RowNumber int primary key, ArticleID int);
Create nonclustered index IX_OrderedRows_ByArticled on #OrderedRows (ArticleID);
insert into #OrderedRows
Select ROW_NUMBER() Over(Order by LastEditDate desc, ArticleOrder Asc, LastEditDateTime desc) as RowNumber, Article_tbl.ArticleID
From Article_tbl
INNER JOIN ArticleZone_tbl
ON dbo.Article_tbl.ArticleID = dbo.ArticleZone_tbl.ArticleID
Where ChannelID=1 And ZoneID=0
SELECT oo.RowNumber, at.*, azt.ChannelID, azt.ZoneID, azt.ArticleOrder
FROM #OrderedOrders oo
join Article_tbl at
on oo.ArticleID = at.ArticleID
INNER JOIN ArticleZone_tbl azt
ON at.ArticleID = azt.ArticleID
and azt.ChannelID = 1
and azt.ZoneID = 0
Where oo.RowNumber Between 1 And 10
Drop table #OrderedRows;
此外,添加以下索引会影响性能吗?
create nonclustered index IX_Article_tbl_ByArticle_IncOrder on Article_tbl (ArticleID) Include (ArticleOrder);
create nonclustered index IX_ArticleZone_tbl_Cover on ArticleZone_tbl (ChannelID, ZoneID, ArticleID, ArticleDate, ArticleTime);