【问题标题】:index is not working while using ROW_NUMBER in sql server在 sql server 中使用 ROW_NUMBER 时索引不起作用
【发布时间】:2013-02-09 03:42:01
【问题描述】:

我已使用 Row_Number() 在我的存储过程中实现分页。分页工作正常。但问题是,在实现 Row_Number() 之后,索引不起作用,即使我按部分顺序使用主键列,也会发生聚集索引扫描。 以下是示例查询:

SELECT TOP (@insPageSize) A.RowNum, A.AdID, A.AdTitle, A.AdFor, A.AdCondition, 
A.AdExpPrice, A.CreatedDate, A.ModifiedDate, A.AdUID
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY vaa.AdID DESC) AS RowNum,
    vaa.AdID, vaa.AdTitle, vaa.CityID, vaa.AdFor, vaa.AdCondition, 
    vaa.AdExpPrice, vaa.CreatedDate, vaa.ModifiedDate, vaa.AdUID
FROM Catalogue.vwAvailableActiveAds vaa
WHERE vaa.CategoryID = @intCategoryID AND vaa.CountryCode = @chrCountryCode 
        AND vaa.CreatedDate > DATEADD(dd, -90, GETUTCDATE()) 
        AND vaa.StateID = @inbStateID AND vaa.CityID = @inbCityID
) A
WHERE A.RowNum > (@insPageSize * (@insPageNo - 1))

如果我尝试只执行内部查询:

 SELECT ROW_NUMBER() OVER (ORDER BY vaa.AdID DESC) AS RowNum,
    vaa.AdID, vaa.AdTitle, vaa.CityID, vaa.AdFor, vaa.AdCondition, 
    vaa.AdExpPrice, vaa.CreatedDate, vaa.ModifiedDate, vaa.AdUID
FROM Catalogue.vwAvailableActiveAds vaa
WHERE vaa.CategoryID = @intCategoryID AND vaa.CountryCode = @chrCountryCode 
        AND vaa.CreatedDate > DATEADD(dd, -90, GETUTCDATE()) 
        AND vaa.StateID = @inbStateID AND vaa.CityID = @inbCityID

它不使用任何索引。 AdID 是主键,还有另一个非聚集索引涵盖所有 where 子句。但是会发生索引扫描。如果我从内部查询中删除 Row_Number() 并检查其执行计划,所有索引都可以正常工作,但 StateID 和 CityID 在非聚集索引中时再次显示为“谓词”。

请给我一些指导来解决我的这两个问题。

【问题讨论】:

    标签: sql sql-server row-number non-clustered-index


    【解决方案1】:

    row_number() 没有使用索引,因为必须先过滤数据。而且,这似乎需要全表扫描。或者,至少是复杂的索引组合。

    如果您在vwAvailableActiveAds(CategoryId, COuntryCode, StateId, CityId, CreatedDate) 上建立索引,那么它应该将此索引用于where 子句。 row_number() 的应用程序仍然不会使用索引,但可能会使用更小的数据集。

    顺便说一句,这假定视图实际上只是基础表上的一个选择。如果视图中的查询更复杂(即使使用where 子句、joingroup by),那么该特定索引可能不是最佳方法。

    【讨论】:

    • 嗨,Gordon,视图包含来自 4 个表的数据,并且在这些表中使用聚集索引查找。在我的查询中,where 子句仅包含基表的过滤器,我的非聚集索引序列是:(categoryID、countrycode、createddate、stateID、cityID)包括(title、adfor、condition、price、modifieddate)。 AdUid 来自我在连接中使用的第二个表,该表有一个聚集索引,它正在利用它的索引搜索。
    • @AnujRathi 。 . .您需要在字段列表的末尾添加createddate。它用于where 子句中的不等式。
    • 感谢您的建议。我还搜索了一些其他网站,我认为这将是一个不错的选择。
    【解决方案2】:

    你期待什么,寻找?您在这里做了几件事,这使得执行查找变得非常困难:(a)返回一个 RANGE 行; (b) 按 AdID DESC 排序以获得 ROW_NUMBER() - 可能不是您的 PK 定义的顺序; (c) 过滤除 PK 以外的其他内容,以及 (d) 在输出中包括许多不太可能被任何 NC 索引覆盖的列。很多人把手举在空中,大喊:“天哪!这是扫描!这太可怕了!”即使在实际上这是最有效的方法的情况下。

    (仅仅因为没有发生搜索并不意味着“索引不起作用” - 这只是意味着它们在满足此查询方面可能会更有效。)

    【讨论】:

    • 嗨亚伦,感谢您的回答。我创建了非聚集索引,它涵盖了“include”子句中的所有“where”列和选定的列。如果我在没有 Row_Number 的情况下运行上述查询,则存在索引搜索。
    • @Anuj 您希望如何通过仅执行查找来确定表中每一行的行号?想一想。
    猜你喜欢
    • 1970-01-01
    • 2021-04-10
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多