sql - 加速分区 ROW_NUMBER()
问题描述
我目前有这个查询(SQL Server):
DECLARE @PageNum int = 1;
DECLARE @PageSize int = 2;
SELECT *
FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY Color ORDER BY Name) AS Row
FROM Orders
) t1
WHERE Row BETWEEN ((@PageNum-1)*@PageSize+1) AND (@PageNum*@PageSize)
ORDER BY Color,Name
这个查询的作用是它为每个选择带有 2 条记录的“页面” Color
。意思是如果表包含:
ID | 颜色 | 姓名 |
---|---|---|
1 | 红色的 | 论文#1 |
2 | 红色的 | 论文#2 |
3 | 红色的 | 论文#3 |
4 | 绿 | 论文#4 |
5 | 绿 | 论文#5 |
6 | 绿 | 论文#6 |
7 | 绿 | 论文#7 |
那么上面的查询将导致:
ID | 颜色 | 姓名 |
---|---|---|
1 | 红色的 | 论文#1 |
2 | 红色的 | 论文#2 |
4 | 绿 | 论文#4 |
5 | 绿 | 论文#5 |
在第 1 页和
ID | 颜色 | 姓名 |
---|---|---|
3 | 红色的 | 论文#3 |
6 | 绿 | 论文#6 |
7 | 绿 | 论文#7 |
在第 2 页。
这行得通。但是,在我的实际示例中,此查询需要很长时间才能执行——实际上大约需要 10 分钟。我有一个包含超过 80 万条记录的静态表,这些记录永远不会改变。由于该表永远不会更改,因此我为要过滤/排序的每一列创建了一个索引。该表还有一个 column RowId
,实际上只是行号,并且它具有唯一索引。
执行计划可以在这里看到:https ://www.brentozar.com/pastetheplan/?id=BkeWfVCSY
我能做些什么来加快这个查询?
解决方案
您的执行计划中的第一个操作是表扫描,所以我假设这是一个堆表(否则我们应该看到聚集索引扫描)并且您创建的索引没有被使用。
此外,一旦这是一个永远不会改变的静态表,根据描述,碎片应该不是问题。
我没有在这台机器上安装 SQL Server,所以我无法比较之前和之后的执行计划,但我相信对于您的查询,我们可能会看到聚集索引的一些改进,按照 Martin Smith 的建议对键进行排序他的评论。
CREATE CLUSTERED INDEX IX_Order ON dbo.Order(OrderType ASC, From DESC)
请让我知道这是否可以改善您的查询。如果没有,我可以创建一个类似的场景在白天进行测试。
推荐阅读
- java - org.springframework.jdbc.CannotGetJdbcConnectionException,嵌套异常是java.sql.SQLException
- javascript - Angular APPINITIALIZER TypeError:未定义不是对象和承诺
- cognos - Cognos 11 - 查询主题之间的过滤器
- c# - 网页中与脚本相关的 HTML 标记的不正确中和(基本 XSS)CWE ID 80
- php - 如何解决rest api中的CORS预检错误
- python-3.x - 熊猫:插入缺少的工作日(不基于日期)并用零填充
- javascript - 将函数作为道具传递给另一个组件
- python - 在遍历 for 循环(PANDAS)中的列时,有什么方法可以使 if 比较更快?
- c - 有没有办法将 0.15 转换为 15
- python - 如何创建具有 2 维的单个向量?