为啥使用选择前 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%?老是没响应,怎么办?
为啥这个微不足道的 opengl 程序使用 100% cpu?