多连接数百万条记录的优化查询需要建议
Posted
技术标签:
【中文标题】多连接数百万条记录的优化查询需要建议【英文标题】:Need suggestion on optimization query of multiple million of records with multiple joins 【发布时间】:2017-10-21 11:15:01 【问题描述】:如何优化此查询,因为 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
【问题讨论】:
使用Paste The Plan @ brentozar.com 分享您的执行计划,以下是说明:How to Use Paste the Plan。 如前所述共享您的表 DDL 和执行计划。 @artashes Khachatryan 实际上,这只是一段代码,仅在左连接方面需要优化的地方。还有其他内部连接,无论如何这都是必要的,但我在这里没有提到。 @MonkeyD.luffy 我们需要查看包含在此查询中的表的创建语句以帮助您。 【参考方案1】:从可见的情况来看,我认为优化器的问题是运气知道左连接是否重复 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
【讨论】:
这个建议让我大大优化了查询时间,谢谢【参考方案2】:这回答了问题的原始版本(通用 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)
上的索引。
【讨论】:
我只能使用 SQL2008R – @MonkeyD.luffy,我在您的问题中添加了特定于版本的标签。以上是关于多连接数百万条记录的优化查询需要建议的主要内容,如果未能解决你的问题,请参考以下文章
具有数百万条记录的 2 个数据帧之间的 Pyspark 交叉连接
优化返回大量记录的查询,避免数百个连接。这是一个聪明的解决方案吗?
与 laravel 在处理数百万条记录时使用块的普通查询构建器相比,Laravel Eloquents 和使用块是不是更慢?