SQL Server中`select field from table`的返回顺序及clustered index的影响
核心确定性结论
- 只要SQL语句没有显式带上
ORDER BY子句,SQL Server从来不会对返回结果的行顺序做任何固定保证,不管查询的是单字段还是多字段、不管表是什么存储结构 - 你观测到的返回结果和表存储顺序吻合,只是当前环境下优化器选的执行计划刚好和存储扫描路径重合,完全是偶然结果,不是数据库承诺的固定行为
- 表是否带聚集索引,确实会影响特定场景下的临时返回顺序,但绝对不会给这个顺序加上任何可依赖的稳定性:
- 带聚集索引的表:聚集索引的叶子节点就是表的实际数据页,全表数据是严格按照聚集索引键的顺序逻辑组织的。当优化器选择聚集索引全扫描的执行路径时,单字段查询返回的行顺序,就是顺着聚集键排序方向遍历的结果,看起来和表的存储组织顺序完全一致
- 堆表(没有聚集索引的表):不存在统一的逻辑排序结构,全表扫描是顺着索引分配映射(IAM)页遍历所有属于表的数据页,返回顺序和数据页的物理位置、碎片率、历史增删改操作留下的痕迹相关,根本没有稳定的排序规律
常见的会打破“存储顺序返回”的场景
- 执行计划从串行扫描切到并行扫描:多线程分片扫描的结果合并顺序没有固定规则,哪怕仍然走聚集索引路径,最终返回的行顺序也会和单线程扫描的结果不一样
- 优化器主动切换执行路径:当单字段查询带过滤条件、或者表上存在能覆盖该查询的非聚集索引时,只要优化器算出来非聚集索引扫描的成本更低,就会切到非聚集索引的遍历路径,返回顺序会和非聚集索引的键值排序保持一致,不再匹配原来的聚集索引存储顺序
- 表和数据状态变化:统计信息更新、数据量大幅变动、索引重建/重组、页拆分导致碎片率变化,都会触发优化器重选执行计划,你之前观测到的“按存储顺序返回”的结果可能直接失效
写业务代码的时候,绝对不能依赖不带
ORDER BY的查询的隐式返回顺序做逻辑判断(比如实现分页、按顺序做累加计算这类操作),想要拿到100%可预期的稳定返回顺序,必须在查询末尾显式写清楚ORDER BY的排序规则。
内容的提问来源于stack exchange,提问作者Vyacheslav Ratushnyy
相关产品推荐
相关产品推荐

