需要对具有多个连接的数百万条记录的优化查询提出建议

时间:2017-10-21 11:15:02

标签: sql-server tsql join sql-server-2008-r2 query-optimization

如何优化此查询,因为EXT表每个包含大约150万条记录。我还有其他联接,但他们的记录相对少于50。 两个EXT表都使用默认设置设置了标识,并且是P

SELECT *
FROM (
  SELECT
    ROW_NUMBER() OVER(ORDER BY ID ASC) AS RowNumber
    , *
  FROM History
    LEFT JOIN FlattenExt1 
      ON History.ID = FlattenExt1.ExtID
    LEFT JOIN FlattenExt2 
      ON History.ID = FlattenExt2.ExtId
  ) as final
where final.RowNumber BETWEEN (@PageIndex -1) * @PageSize + 1
                          AND (((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1
order by final.rownumber

2 个答案:

答案 0 :(得分:2)

从可见的,我相信优化器的问题是运气,知道左连接是否重复HISTORY.ID值,影响ROW_NUMBER。 如果左连接条件的每个历史记录行的连接限制为0-1行,则仅对历史记录执行ROW_NUMBER,获取ID,然后加入

DECLARE @page INT = 150 , @rows INT = 10
;WITH 
data AS (SELECT ID  FROM History)
,rows (page, pages, rows) AS ( SELECT @page, CEILING(CAST(COUNT(*) AS float)/@page), COUNT(*) FROM data )
SELECT * FROM history INNER JOIN 
    (SELECT TOP (@rows) rowNumber,page, pages, rows,ID 
          FROM ( SELECT row_number() OVER (ORDER BY ID  ASC ) rowNumber, * FROM rows, data ) pagination
          WHERE rowNumber > (@page-1) * @rows
          order by rowNumber
    )historypageids ON history.ID = historypageids
LEFT JOIN FlattenExt1 ON History.ID = FlattenExt1.ExtID
LEFT JOIN FlattenExt2 ON History.ID = FlattenExt2.ExtId

答案 1 :(得分:0)

这回答了问题的原始版本(通用SQL Server)。

以下内容仅适用于SQL Server 2012 +。

如果您不需要row_number()值,我建议:

 SELECT . . .
 FROM History h LEFT JOIN
      FlattenExt1 f1
      ON h.ID = f1.ExtID LEFT JOIN
      FlattenExt2 f2
      ON h.ID = f2.ExtId                                                           
 ORDER BY h.ID
 OFFSET (@PageIndex -1) * @PageSize + 1 
 FETCH NEXT @PageSize ROWS;

这应该能够利用History(ID)FlattenExt1(ExtId)FlattenExt2(ExtId)上的索引。