繁体   English   中英

在SQL Server中,在具有聚簇索引的表上使用时,默认情况下是TOP确定性的吗?

[英]In SQL Server, is TOP deterministic by default when used on a table with a clustered index?

所以我试图向一些人解释为什么这个查询是个坏主意:

SELECT z.ReportDate, z.Zipcode, SUM(z.Sales) AS Sales,
COALESCE(
  (SELECT TOP (1) GroupName
  FROM dbo.zipGroups
  WHERE (Zipcode = z.Zipcode)), 'Unknown') AS GroupName,
COALESCE(
  (SELECT TOP (1) GroupCode
  FROM dbo.zipGroups
  WHERE (Zipcode = z.Zipcode)), 0) AS GroupNumber
FROM dbo.Report_ByZipcode AS z
GROUP BY z.ReportDate, z.Zipcode

并建议一个更好的方式来写它,当我的老板结束讨论时,“嗯,它已经返回了去年的正确数据,我们没有遇到任何问题,所以没关系。”

在这一点上,我心想,世界上甚至可能是这样吗?

经过一番挖掘,我发现了这些事实:

  1. 此查询应按Zipcode和date对销售进行分组,并将这些内容链接到ZipGroup分配给ZipGroups表的最大组(按人口大小)。
  2. 每个Zipcode可以分配到0到多个组,如果Zipcode被分配到0个组,它就不在zipGroups表中。
  3. A组是地理区域,GroupNumbers按人口从最大到最小排名(例如,覆盖NY-NJ-CT三态区域的组是GroupNumber 1,而North Platte,Nebraska是GroupNumber 209)。
  4. zipGroups表至少在2年内没有变化。
  5. zipGroups表有一个聚集索引,Zipcode,GroupNumber(升序)作为键。
  6. Zipcode,GroupNumber的组合在zipGroups中是唯一的。

所以我的问题有2个部分。

A)即使SELECT TOP查询中没有ORDER BY子句,它们实际上是确定性的,因为聚簇索引基本上是为它提供默认的ORDER BY吗?

B1)如果这是真的,那么查询是否会岌岌可危 ,实际上正在做它应该做的事情?

B2)如果不是这样,你能帮我证明一下吗?

注意:我已经重写了这个以使用连接,所以我不需要SQL来修复它,我需要将它投入生产中,所以我不再担心它会破坏。

在没有ORDER BY的情况下,SQL Server不保证记录的顺序。 它可能产生正确的结果999,999次,然后在第一百万次尝试失败。 不要这样做。

始终使用TOP声明使用订单。 订单不保证是聚集索引的顺序,如本博客文章中所示(包含反驳它的查询):

没有ORDER BY,没有默认的排序顺序

即使它确实通过聚集索引,我也不会编写依赖于数据库引擎的未记录行为的查询,并且最好明确可读性。

如果你依赖的是聚集索引而不是整理,那么获得正确的顺序是巧合的,而不是确定性的。

在现实世界中,索引可以从一种变为另一种,原因很多,原因很糟糕,或根本没有理由。 而且,在现实世界中,您不一定要选择SQL Server在执行查询时使用的索引。 (或者它是否会使用索引。)

从技术上讲,整理也可能因为充分的理由,不好的理由或根本没有理由而改变。 但是每个人都知道改变整理会改变排序顺序 - 毕竟这是它的工作 - 所以这并不奇怪。 (听说过“最不惊讶的原则”?)

JohnFx的链接很好,尽管很长很难以理解。 这是一个小小的片段,它将显示以非聚集索引顺序返回的数据。

CREATE TABLE t1 (x INT NOT NULL PRIMARY KEY CLUSTERED, z INT NOT NULL UNIQUE);

INSERT INTO t1 (x,z) VALUES (1,4);
INSERT INTO t1 (x,z) VALUES (3,3);
INSERT INTO t1 (x,z) VALUES (2,2);
INSERT INTO t1 (x,z) VALUES (4,1);

SELECT x, z FROM t1;

输出(你应该得到)

x           z
----------- -----------
4           1
2           2
3           3
1           4

执行计划使用唯一(或其他)索引而不是聚集索引来显示它。

即使选择了聚簇索引,如果数据从并行性中合并,如果TOP N计数足够高,则可能无法正确排序。

话虽如此,因为你只使用TOP(1) 并且如果表只有一个索引可用,它可以被认为是确定性的,因为它只会使用该索引并选择索引页中的第一个条目。

A)即使SELECT TOP查询中没有ORDER BY子句,它们实际上是确定性的,因为聚簇索引基本上是为它提供默认的ORDER BY吗? B1)如果这是真的,那么查询是否会岌岌可危,实际上正在做它应该做的事情?

如果指定top而没有排序,则排序是查询优化器选择的访问方法的副作用。 由于查询优化器将使用聚集索引来解析此查询,因此会产生非常好的副作用。

我不会使用确定性这个词,因为查询优化器可能不是确定性的。 但是,在优化器选择聚簇索引的情况下,是 - 查询执行它应该执行的操作。

仍应指定ORDER,以便将正确性锁定到查询中。 应该分别将正确性(“你想要什么”)和实现(“你如何得到它”)分成查询和优化器计划。

B2)如果不是这样,你能帮我证明一下吗?

假设ZipGroups表中有更多列,则可以添加包含仅两个相关列的非聚集索引,这些列优先于聚簇索引。 如果非聚集索引具有不同的排序(Zipcode asc,GroupNumber desc),则查询将中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM