为啥使用选择前 100%?

Posted

技术标签:

【中文标题】为啥使用选择前 100%?【英文标题】:Why use Select Top 100 Percent?为什么使用选择前 100%? 【发布时间】:2009-10-26 02:49:52 【问题描述】:

我了解,在 SQL Server 2005 之前,您可以“欺骗”SQL Server 以允许在视图定义中使用 order by,还可以在 SELECT 中包含 TOP 100 PERCENT 子句。但是我已经看到我继承的其他代码在动态 SQL 语句中使用 SELECT TOP 100 PERCENT ...(在 ASP.NET 应用程序中的 ADO 中使用等)。这有什么原因吗?结果是不是和 not 一样,包括TOP 100 PERCENT

【问题讨论】:

也许有一些语句构造正在进行:“SELECT TOP 0 PERCENT...” 你的第一句话已经成为我隐藏问题的答案。 我使用前 99.9999999 PERCENT,它总是有效。它足够接近。我倾向于根据预期的记录数量附加“9”的数量。更多的记录,更多的 9,它总是有效的。我使用过 SQL 2008 到 SQL 2017。 【参考方案1】:

用于“intermediate materialization (Google search)”

好文章:Adam Machanic: Exploring the secrets of intermediate materialization

他甚至提出了an MS Connect,因此可以以更清洁的方式完成

我的观点“本质上并不坏”,但除非 100% 确定,否则不要使用它。问题是,它仅在您执行此操作时才有效,并且可能以后不会(补丁级别、架构、索引、行数等)...

工作示例

这可能会失败,因为您不知道评估事物的顺序

SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100

这也可能失败,因为

SELECT foo
FROM
    (SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
    CAST(foo AS int) > 100

但是,这在 SQL Server 2000 中没有。内部查询被评估和假脱机:

SELECT foo
FROM
    (SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
    CAST(foo AS int) > 100

注意,这在 SQL Server 2005 中仍然有效

SELECT TOP 2000000000 ... ORDER BY...

【讨论】:

为什么第二次查询失败?因为内部查询没有(必然)完全评估? 第二个链接解释了为什么创建临时表有时会带来显着的性能提升!【参考方案2】:

TOP (100) PERCENT 在最新版本的 SQL Server 中完全没有意义,并且它(连同相应的 ORDER BY,在视图定义或派生表的情况下)被查询处理器忽略。

你说得对,从前它可以被用作一种诡计,但即便如此它也不可靠。可悲的是,微软的一些图形工具把这个毫无意义的条款放进去了。

至于为什么这会出现在动态SQL中,我不知道。你是对的,没有它的理由,没有它的结果是一样的(同样,在视图定义或派生表的情况下,没有 TOP 和 ORDER BY 子句)。

【讨论】:

这不是真的;有关详细信息,请参阅@gbn 的答案中的link。 您引用的链接没有说明 SELECT TOP (100) PERCENT .. ORDER BY,这毫无意义。该链接提到使用 SELECT TOP (2147483647) .. ORDER BY。目前,SQL Server 优化器将消除 SELECT TOP (100) PERCENT .. ORDER BY,因为它没有意义。该组合始终定义与没有 TOP/ORDER BY 的 SELECT 相同的行集合。优化器当前不会尝试确定 2147483647 是否包含所有行,因此在这种情况下它不会消除 TOP - ORDER BY 组合。 该链接实际上确实提到了TOP (100) PERCENT:“......我可能会尝试通过将TOP 100 PERCENT与ORDER BY结合使用来强制派生表的中间实现,没有临时表。不幸的是, SQL Server 查询优化器团队认为这不是一个好主意,优化器现在忽略了这种尝试。”事实上,它支持你。 I'd undo my downvote if I could。 [如果你编辑你的答案,我会投赞成票。] 你可能很困惑,因为我改变了主意;我的第一条评论是错误的;你是对的。【参考方案3】:

...允许在视图定义中使用 ORDER BY。

这不是一个好主意。视图永远不应定义 ORDER BY。

一个 ORDER BY 对性能有影响 - 使用它一个视图意味着 ORDER BY 将出现在解释计划中。如果您有一个查询,其中视图连接到即时查询中的任何内容,或在内联视图中引用(CTE/子查询分解) - ORDER BY 始终在最终 ORDER BY 之前运行(假设它已定义)。当查询不使用 TOP(或 mysql/Postgres 的 LIMIT)时,对不是最终结果集的行进行排序没有任何好处。

考虑:

CREATE VIEW my_view AS
    SELECT i.item_id,
           i.item_description,
           it.item_type_description
      FROM ITEMS i
      JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
  ORDER BY i.item_description

...

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM my_view t
ORDER BY t.item_type_description

...等价于使用:

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM (SELECT i.item_id,
                 i.item_description,
                 it.item_type_description
            FROM ITEMS i
            JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
        ORDER BY i.item_description) t
ORDER BY t.item_type_description

这很糟糕,因为:

    该示例最初按项目描述对列表进行排序,然后根据项目类型描述重新排序。它在第一类中浪费了资源 - 按原样运行 not 意味着它正在运行:ORDER BY item_type_description, item_description 由于封装,视图的排序方式并不明显。这并不意味着您应该创建具有不同排序顺序的多个视图...

【讨论】:

【参考方案4】:

如果没有ORDER BY 子句,那么TOP 100 PERCENT 是多余的。 (正如你提到的,这是视图的“技巧”)

[希望优化器能将其优化掉。]

【讨论】:

【参考方案5】:

我已经看到我继承的其他代码使用 SELECT TOP 100 PERCENT

这样做的原因很简单:企业管理器曾经尝试提供帮助并格式化您的代码以包含此内容。尝试移除它是没有意义的,因为它并没有真正伤害任何东西,下次你去改变它时,EM 会再次插入它。

【讨论】:

【参考方案6】:

我猜没有理由,只是冷漠。

此类查询字符串通常由图形查询工具生成。用户加入几个表,添加过滤器、排序顺序并测试结果。由于用户可能希望将查询保存为视图,因此该工具添加了 TOP 100 PERCENT。但是,在这种情况下,用户将 SQL 复制到他的代码中,参数化 WHERE 子句,并将所有内容隐藏在数据访问层中。心不在焉,眼不见为净。

【讨论】:

【参考方案7】:

请尝试以下方法,希望对您有用。

      SELECT TOP
              ( SELECT COUNT(foo) 
                  From MyTable 
                 WHERE ISNUMERIC (foo) = 1) * 
                  FROM bar WITH(NOLOCK) 
              ORDER BY foo
                 WHERE CAST(foo AS int) > 100
               )

【讨论】:

【参考方案8】:

错误说明了一切......

Msg 1033,级别 15,状态 1,过程 TestView,第 5 行 ORDER BY 子句在视图、内联函数、派生表中无效, 子查询和公用表表达式,除非 TOP、OFFSET 或 FOR 还指定了 XML。

不要使用TOP 100 PERCENT,使用TOP n,其中N是一个数字

SQL Server VIEW(2012 年后版本)忽略了 TOP 100 PERCENT(出于我不知道的原因),但我认为 MS 出于语法原因保留它。 TOP n 更好,它将在视图中工作,并在最初使用视图时按照您想要的方式对其进行排序,但应为 careful。

【讨论】:

【参考方案9】:

我假设您可以在结果中使用变量,但除了在视图中获取 ORDER BY 片段之外,隐含地声明“TOP 100 PERCENT”您不会看到任何好处:

declare @t int
set @t=100
select top (@t) percent * from tableOf

【讨论】:

问题是Why use Select Top 100 Percent 不获取百分比的变量计数。【参考方案10】:

试试这个,它本身就解释得很清楚。您不能使用 ORDER BY 创建视图,除非...

CREATE VIEW v_Test
         AS
           SELECT name
             FROM sysobjects
         ORDER BY name
        GO

Msg 1033,级别 15,状态 1,过程 TestView,第 5 行 ORDER BY 子句在视图、内联函数、派生表中无效, 子查询和公用表表达式,除非 TOP、OFFSET 或 FOR 还指定了 XML。

【讨论】:

以上是关于为啥使用选择前 100%?的主要内容,如果未能解决你的问题,请参考以下文章

win10系统,任务管理器那里硬盘为啥是100%?老是没响应,怎么办?

为啥 CPU 使用率和线程数会达到 99-100%?

为啥这个微不足道的 opengl 程序使用 100% cpu?

为啥只有 25 个并发用户,服务器 CPU 使用率达到 100%?

为啥 css 动画不适用于背景大小 100%

弄清楚为啥 Flash(Firefox 插件)在递归 NP_Initialize 上使用 100% CPU