2

我正在尝试建立分页机制。我正在使用创建如下 SQL 的 ORM:

SELECT * FROM 
    (SELECT t1.colX, t2.colY
         ROW_NUMBER() OVER (ORDER BY t1.col3) AS row 
     FROM Table1 t1
     INNER JOIN Table2 t2
     ON t1.col1=t2.col2
    )a 
WHERE row >= n AND row <= m

Table1 有 >500k 行,Table2 有 >10k 记录

我直接在 SQL Server 2008 R2 Management Studio 中执行查询。子查询需要 2-3 秒才能执行,但整个查询需要 > 2 分钟。

我知道 SQL Server 2012 接受该OFFSET .. LIMIT ..选项,但我无法升级软件。

任何人都可以帮助我提高查询的性能或建议可以通过 ORM 软件强加的其他分页机制。

Update:

测试Roman Pekar的解决方案(参见解决方案的评论)证明 ROW_NUMBER() 可能不是性能问题的原因。不幸的是,问题仍然存在。

谢谢

4

3 回答 3

3

正如我从评论中了解您的表结构一样。

create table Table2
(
  col2 int identity primary key,
  colY int
)

create table Table1
(
  col3 int identity primary key,
  col1 int not null references Table2(col2),
  colX int
)

这意味着从返回的行Table1永远不会被连接过滤到,Table2因为Table1.col1is not null。连接也不能将Table2行添加到结果中,因为Table2.Col2它是主键。

然后,您可以重写您的查询以Table1在加入之前生成行号Table2。并且 where 子句也适用于连接之前,Table2这意味着您只会找到Table2实际上是结果集一部分的行。

select T1.colX,
       T2.colY,
       T1.row
from
    (
    select col1,
           colX,
           row_number() over(order by col3) as row
    from Table1
    ) as T1
  inner join Table2 as T2
    on T1.col1 = T2.col2
where row >= @n and row <= @m

SQL小提琴

我不知道你是否可以让你的 ORM(Mindscape 的 Lightspeed)生成这样的分页查询,而不是你现在拥有的。

此答案的查询计划: 在此处输入图像描述

使用问题中的查询的查询计划: 在此处输入图像描述

两者之间的读取存在巨大差异。

在此处输入图像描述

于 2013-08-08T10:21:34.930 回答
1

仅将分页表的主键列插入到具有标识列的临时表中,按排序列排序。(您可能必须包含有序列以确保排序正确。)然后,使用临时表作为所需行的键连接回主表。如果数据是相当静态的,您可以将排序数据保存到会话键控永久表而不是临时表,并在短时间内重复使用它(因此几分钟内的后续页面请求几乎是即时的)。

Row_Number() 往往在处理少量数据时表现良好,但一旦你得到一些严重的行,它就会遇到严重的性能障碍,就像你在 500k 时一样。

于 2013-08-05T16:15:54.997 回答
0

我建议您检查表上的索引。如果您至少在 oncol2上有索引,我认为这将有助于您的查询table2。您也可以尝试重写您的查询,例如

;with cte1 as (
    select top (@m) t1.colX, t2.colY, t1.col3
    from Table1 as t1
        inner join Table2 as t2 on t1.col1=t2.col2
    order by t1.col3 asc
),
cte2 as (
    select top (@m - @n + 1) *
    from cte1
    order by col3 desc
)
select *
from cte2 as t1

但如果你没有索引,它仍然可能很慢

于 2013-08-05T17:48:06.493 回答