sql-server - 默认情况下(不带 orderby)从分区表中按降序获取数据
问题描述
我正在尝试学习在 SQL Server 中对单个表进行分区并实现https://www.sqlshack.com/database-table-partitioning-sql-server/中给出的示例。
问题:我在名为的表上的分区Reports
基于名为 的列ReportDate
。
当我从分区表中检索记录时,它们总是按升序(默认)排序,ReportDate
即使我ReportDate
按降序创建了聚集索引。
Select top 10 *
from Reports
此查询返回如下记录:
2020-01-01
2020-02-01
.
.
.
预期结果:
2020-12-31
2020-11-30
.
.
.
我的默认用例是先获取最新记录,我们可以在分区表中进行吗?如果是,如何?
解决方案
ORDER BY
省略时没有“默认”顺序。顺序是“未定义的”,因此 SQL Server 可以按照它选择的任何顺序返回行。由于索引、隔离级别、并行性和分区等因素,这种未定义的顺序可能会有所不同。此外,顺序可能因 SQL Server 版本、版本、补丁级别以及风向而异。ORDER BY
如果您需要按特定顺序返回的结果,则需要。
话虽如此,琐碎SELECT * FROM Reports
查询的实际执行计划揭示了为什么未定义的顺序在有和没有表分区的情况下会有所不同。ReportDate
由于READ_COMMITTTED
隔离级别,这两个计划都显示访问第一个(并且仅在非分区表的情况下)分区,并返回行并按键顺序(降序)扫描聚集索引。
<RunTimePartitionSummary>
<PartitionsAccessed PartitionCount="1">
<PartitionRange Start="1" End="1" />
</PartitionsAccessed>
</RunTimePartitionSummary>
<IndexScan Ordered="false" ForcedIndex="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[tempdb]" Schema="[dbo]" Table="[Reports]" Column="ReportDate" />
</DefinedValue>
</DefinedValues>
<Object Database="[tempdb]" Schema="[dbo]" Table="[Reports]" Index="[cdx]" IndexKind="Clustered" Storage="RowStore" />
</IndexScan>
但是请注意,分区表的第一个分区仅包含小于或等于第一个分区边界的行(使用RANGE LEFT
分区函数)。分区表查询的“未定义”顺序是分区函数边界月份升序后ReportDate
降(每个分区内的聚集索引键序列)。
一个重要的旁注是索引策略在有和没有分区的情况下是不同的。分区号在概念上类似于最左边的索引键。在这种情况下,具有所需ORDER BY ReportDate DESC
子句和降序索引键的分区表计划不会像人们预期的那样利用降序索引顺序,而是引入了排序运算符(使用 SQL 2019 CU6):
由于 SQL Server 可以向前和向后遍历 b 树索引,因此没有必要使用单个键创建降序索引。具有升序索引的计划使用更有效的向后扫描来提供排序:
推荐阅读
- python - 如何在Python中提取具有多列条件的行
- sql - 将多个选择查询与不同的 where 子句相结合
- javascript - 一个以数组为参数的函数,带有一个 forEach 循环,该循环控制台记录函数内每次迭代的每个元素和每个索引
- python - 从 Wikipedia 上的 BeautifulSoup webscrape 中查找 TICKR 编号
- python - python请求中缺少身份验证参数(401)
- vue.js - 如何将 axios 的响应传递给 axios 外部的变量
- android - 为什么我的盒子阴影没有在 Android 上显示?
- javascript - 类中的回调问题(未检测到在方法关闭时调用函数)
- python-3.x - Pycharm CE:无法启动进程:工作目录不存在
- tensorflow.js - 克隆 Tensorflow.js 加载模型