【问题标题】:Query with row_number() taking too much time使用 row_number() 查询花费太多时间
【发布时间】:2012-10-17 03:49:57
【问题描述】:

我的数据库中有大约 90k 条记录,我运行以下查询:

花费了太多时间(大约 4 秒):

SELECT * FROM (SELECT 
    ROW_NUMBER() OVER (Order By DocumentID desc) peta_rn, peta_query.* From 
    (
            Select   d.DocumentID, d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, dbo.GetLatestStatusDateTime(d.DocumentID) as LatestStatusDatetime, 
                    dbo.FnCanChangeDocumentStatus(d.DocumentStatusID,d.DocumentID) as CanChangeStatus, d.IDate, d.InstrumentID, d.DocumentStatusID,ig.Abbreviation as IGroupAbbreviation, 
                    u.Username, j.JDAbbreviation, inf.DocumentName,
                    it.Abbreviation as ITypeAbbreviation, d.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation,
                    dbo.GetFlatDocumentName(d.DocumentID) as FlatDocumentName 
                    From Documents d Inner Join IGroupes ig On d.IGroupID = ig.IGroupID 
                            Left Join ITypes it On d.ITypeID = it.ITypeID 
                            Left Join Users u On u.UserID = d.UserID 
                            Left Join DocumentStatuses ds On d.DocumentStatusID = ds.DocumentStatusID 
                            Left Join InstrumentFiles inf On d.DocumentID = inf.DocumentID 
                            Inner Join Jurisdictions j on j.JurisdictionID = d.JurisdictionID                           
    ) as peta_query) peta_paged WHERE peta_rn>12000 AND peta_rn<=12100

但是,第二个查询在 1 秒内执行:

SELECT * FROM (SELECT 
    peta_query.* From 
    (
            Select  ROW_NUMBER() OVER (Order By d.DocumentID desc) peta_rn, d.DocumentID, d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, dbo.GetLatestStatusDateTime(d.DocumentID) as LatestStatusDatetime, 
                    dbo.FnCanChangeDocumentStatus(d.DocumentStatusID,d.DocumentID) as CanChangeStatus, d.IDate, d.InstrumentID, d.DocumentStatusID,ig.Abbreviation as IGroupAbbreviation, 
                    u.Username, j.JDAbbreviation, inf.DocumentName,
                    it.Abbreviation as ITypeAbbreviation, d.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation,
                    dbo.GetFlatDocumentName(d.DocumentID) as FlatDocumentName 
                    From Documents d Inner Join IGroupes ig On d.IGroupID = ig.IGroupID 
                            Left Join ITypes it On d.ITypeID = it.ITypeID 
                            Left Join Users u On u.UserID = d.UserID 
                            Left Join DocumentStatuses ds On d.DocumentStatusID = ds.DocumentStatusID 
                            Left Join InstrumentFiles inf On d.DocumentID = inf.DocumentID 
                            Inner Join Jurisdictions j on j.JurisdictionID = d.JurisdictionID                           
    ) as peta_query) peta_paged WHERE peta_rn>12000 AND peta_rn<=12100

我的问题是:

1)您能否建议为什么我的第一个查询需要这么长时间才能执行?我想优化我的第一个查询,因为它是由一个自动化程序生成的(我有它的源,但我不能在 Select 中移动 RowNumber)。

2) 执行此操作的时间也取决于 peta_rn。如果我给 peta_rn > 50000 和 peta_rn

【问题讨论】:

  • 你索引 peta_rn 了吗?它将提高您的查询性能。
  • @habibillah:我应该如何索引 peta_rn?它只是一个计算字段 * ROW_NUMBER() OVER (Order By d.DocumentID desc)*

标签: sql sql-server sql-server-2008


【解决方案1】:

只是为了好玩 - 你能试试这个 CTE 看看它的表现吗?我不完全明白为什么你在那里有三个嵌套的子查询......

;WITH PetaQuery AS
(
    SELECT 
        ROW_NUMBER() OVER (ORDER BY d.DocumentID DESC) peta_rn, 
        d.DocumentID, d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, 
        dbo.GetLatestStatusDateTime(d.DocumentID) as LatestStatusDatetime, 
        dbo.FnCanChangeDocumentStatus(d.DocumentStatusID,d.DocumentID) as CanChangeStatus, 
        d.IDate, d.InstrumentID, d.DocumentStatusID,ig.Abbreviation as IGroupAbbreviation, 
        u.Username, j.JDAbbreviation, inf.DocumentName,
        it.Abbreviation as ITypeAbbreviation, d.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation,
        dbo.GetFlatDocumentName(d.DocumentID) as FlatDocumentName 
    FROM 
        Documents d 
    INNER JOIN 
        IGroupes ig On d.IGroupID = ig.IGroupID 
    LEFT OUTER JOIN 
        ITypes it On d.ITypeID = it.ITypeID 
    LEFT OUTER JOIN 
        Users u On u.UserID = d.UserID 
    LEFT OUTER JOIN 
        DocumentStatuses ds On d.DocumentStatusID = ds.DocumentStatusID 
    LEFT OUTER JOIN 
        InstrumentFiles inf On d.DocumentID = inf.DocumentID 
    INNER JOIN 
        Jurisdictions j on j.JurisdictionID = d.JurisdictionID                           
) 
SELECT * FROM PetaQuery
WHERE peta_rn > 12000 AND peta_rn <= 12100

这是否与您的原始查询具有相同的响应时间?

如果是,请检查:

  • 你的所有外键(IGroupIDITypeIDUserIDDocumentStatusIDDocumentIDJurisdictionID)都有索引吗?这对于快速 JOIN 性能至关重要

【讨论】:

  • 这需要 2 秒(在我修复了一些错误之后,例如使用 PetaQuery 代替 peta_query 并使用 d.DocumentID 代替 DocumentID。不,我没有外键索引。让我这样做. 感谢您的提示。
  • 您能否建议为什么执行时间取决于 peta_rn?如果您的查询中有 peta_rn > 52000 AND peta_rn
  • @Jack:检查两个执行计划!他们往往会告诉你很多关于事情是如何运作的以及正在发生的事情......我不认为应该责备row_number() - 更有可能是你的很多LEFT OUTER JOIN .....
猜你喜欢
  • 1970-01-01
  • 2018-01-08
  • 2019-11-14
  • 2012-09-03
  • 2013-07-11
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多